我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python 5.4 定制类

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python 5.4 定制类

定制类


看到类似的__slots__这种形如__xx__的变量或者函数名就要注意,这些在Python中有特殊用途。

Python的class中还有许多这样有特殊用途的函数,可以帮助我们定制类。


__str__

我们先定义一个Student类,打印一个实例:
>>>class Student(object):
    def __init__(self,name):
        self.name =name

>>>print(Student('Michael'))

<__main__.Student object at 0x109afb190>

打印<__main__.Student object at 0x109afb190>不好看,怎么才能好看呢?

只需要定义好__str__()方法, 返回一个好看的字符串就可以了。

>>>class Student(object):

    def __init__(self,name):
        self.name=name

   def __str__(self):
        return 'Student object (name: %s)' % self.name

>>>print(Student('Michael'))

Studnet object (name: Michael)

但是直接敲命令不使用print,打印出来的实例还是不好看:

>>>s =Student('Michael')

>>>s

<__main__.Student object at 0x109afb190>

这是因为直接显示变量调用的不是__str__(),而是__repr__(),两者区别是__str__返回的是用户看到的字符串,__repr__返回程序开发者看到的字符串,也就是说,__repr__()是为调试服务的。

解决办法是在定义一个__repr__()。但通常__str__() __repr__()内容相同。所以有个偷懒的写法:

>>>class Student(object):

    def __init__(self,name):
        self.name=name

   def __str__(self):
        return 'Student object (name: %s)' % self.name

   __repr__ = __str__


__iter__

如果一个类想被用于for ...in循环,类似list或者tuple那样,就必须实现一个__iter__()方法。该方法返回一个迭代对象,然后for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

我们以斐波那契数列为例写一个Fib,可以作用于for循环:
class Fib(object):
    def __init__(self):
        self.a,self.b = 0,1

    def __iter__(self):
        return self

    def __next__(self):
        self.a,self.b =self.b,self.a + self.b

       if self.a >10000:

            raise StopIteration()

        return self.a

>>>for n in Fib():
    print(n)


__getitem__ 

Fib实例虽然能作用于for循环,看起来和list有点像,但是把它当list还是不行的。比如,取第五个元素:
>>>fib()[5]

Traceback (most recent call last):

 File "<stdin>", line 1, in <module>

TypeError: 'Fib' object does not support indexing

要表现得像list那样按照下标读取元素,需要实现__getitem__()方法:
class Fib(object):

    def __getitem__(self,n):
         a,b, =1,1

        for x in range(n):
            a,b =b,a + b

        return a 

现在,就可以像list那样按下标访问数列的任一项了:
>>>Fib()[0]

1

>>>Fib()[1]

1

>>>Fib()[2]

2

>>>Fib()(10)

89

但是list有个神奇的切片方法:
>>>list(range(100))[5:10]

[5,6,7,8,9]

对于Fib却报错。原因是__getitem__()传入的参数可能是一个int,亦可能是一个切片对象slice,所以要做判断:
class Fib(object):
    def __getitem__(self,n):

        if isinstance(n,int):

            a,b =1,1

             for x in range(n):
                a,b =b,a +b

            return a

         if isinstane(n,slice):
            start =n.start

           stop =n.stop

            if start is None:
                start =0

            a,b =1,1

           L =[]

           for x in range(stop):
              if x >=start:
               L.append(a)
              a,b =b,a + b

           return L

现在试试Fib的切片。

>>>f =Fib()

>>>f[0:5]

[1,1,2,3,5]

>>>f[:10]

[1,1,2,3,5,8,13,21,34,55]

但是没有对step参数做处理:
>>>f[:10:2]

[1,1,2,3,5,8,13,21,34,55,89]

也没有对负数做处理,所以,要实现一个__getitem__()函数有很多工作要做。

此外,如果把对象看成dict,__getitem__()的参数也可能是一个可以作key的object如str。

与之对应的是__setitem__()方法,把对象看作list或dict来对集合赋值。最后还有一个__delitem__()方法,用于删除某个元素。

总之,通过上面的方法,我们自定义的类和Python自带的list、tuple、dict没什么区别。这完全归功于动态语言的“鸭子类型”,不需要强制继承某个接口。


__getattr__


正常情况下,当我们调用类的方法或者属性时,如果不存在,就会报错。

要避免这个错误,就写一个__getattr__()动态返回一个属性。修改如下:
class Student(object):
    def __init__(self):
        self.name ='Michael'


    def __getattr__(self,attr):
        if attr == 'score':

            return 99

当调用属性不存在时,比如score,Python解释器会试图调用__getattr__(self,'score')来尝试获得属性,这样,我们就有机会返回score的值:
>>>s =Student()

>>>s.name

Michael

>>>s.socre

99

返回函数也是可以得:

class Student(object):
    def __getattr__(self,attr):
        if attr =='age':

            return lambda:25

调用方式改为:
>>>s.age()

25

注意,只有在没有找到属性的情况下,才会调用__getattr__,已有的属性,比如name,不会在__getattr__中查找。

class Student(object):

   def __getattr__(self, attr):

       if attr=='age':            

           return lambda: 25

       raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)

这实际上是把一个类的所有属性和方法全能动态处理了。不需要任何特殊手段。

这种完全动态调用的特性有什么好处呢?可以针对完全动态的情况调用。

举例,现在好多网站都搞REST API,调用API的URL类似:

  • http://api.server/user/friends

  • http://api.server/user/timeline/list

如果要写SDK,给每个API写一个方法,不现实。而且,API一改,SDK也需要改。

利用完全动态__getattr__,我们可以写出一个链式调用:
class Chain(object):
    def __init__(self,path =''):
        self.path =path

    def __getattr__(self,path):

        return Chain('%s %s' % (self.path,path))

    def __str__(self):
        return self.path

   __repr__ = __str__

试试:
>>>Chain().status.user.timeline.list

'/status/user/timeline/list'

这样,无论API怎样变,SDK都可以根据URL实现完全动态的调用,而且,不随API的增加而改变。

还有些REST API会把参数放到URL中,比如GitHub的API:
GET /users/:user/repos

调用时,需要把:user替换为实际用户名。如果我们 能写出这样的链式调用:
Chain().users('Michael').repos

就可以非常方便的调用API了。有兴趣的同学可以试试写出来。

  

__call__

一个对象实例可以有自己的属性和方法,当我们调用实例方法时,我们用instance.method()来调用。能不能在实例本身上调用方法呢?在Python中答案是肯定的。

任何类,只需定义一个__call__()方法,就直接可以对实例进行调用。

class Student(object):
    def __init__(self,name):

        self.name =name

    def __call__(self):

        print('My name is &s' % self.name)

调用方式如下:
>>>s =Student('Michael')

>>>s()

My name is Michael

__call__()还可以定义参数。对实例进行直接调用就好比对一个函数调用一样,所以,完全可以把对象看成函数,把函数看成 对象,这两者之间本来就没什么区别。

如果你把对象看成函数,那么函数本身其实也可以在运行期间动态创建出来,因为类的实例都是运行期间创建的,这么一来,我们就模糊了对象和函数的界限。

>>> callable(Student())

True

>>> callable(max)

True

>>> callable([1, 2, 3])

False

>>> callable(None)
False
>>> callable('str')

False

通过callable()函数,我们就可以判断一个对象是否是“可调用”。


小结:

Python的class允许定义许多定制方法,可以让我们非常方便的生成特制类。


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python 5.4 定制类

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python 5.4 定制类

定制类看到类似的__slots__这种形如__xx__的变量或者函数名就要注意,这些在Python中有特殊用途。Python的class中还有许多这样有特殊用途的函数,可以帮助我们定制类。__str__我们先定义一个Student类,打印一
2023-01-31

定制类和黑魔法

定制类  反射    反射又称为自省,指的是程序可以访问、检测和修改它本身状态和行为的一种能力。python中提供了以下四个自检功能的函数。    hasattr(object, name):用来检测object(适用于类、文件、模块或对象
2023-01-30

python定义变量类型

目录定义变量什么是变量?变量的定义?标识符(命令规范)命名原则变量的类型不同类型变量之间的计算变量的输入变量的格式化输出变量赋值删除变量常量定义定义变量 什么是变量? 在程序运行过程中,其值可以改变的量 变量的定义? 在 python 中,
2022-06-02

Python导入自定义类

现有自定义类(Color.py)如下,类位于路径’/Users/chuxing/python/test’下:class Color(object): def __init__(self, red, green, blue):
2023-01-31

python中类怎么定义

这篇文章主要介绍了python中类怎么定义,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。类的定义# class是定义类的关键字,ClassName为类的名称class Cla
2023-06-25

python 通过元类控制类的创建

一、python中如何创建类?1. 直接定义类class A:   a = 'a' 2. 通过type对象创建在python中一切都是对象在上面这张图中,A是我们平常在python中写的类,它可以创建一个对象a。其实A这个类也是一个对象,它
2023-01-31

Python - 定制语法的string

定制语法的string模板(template) 详解本文地址: http://blog.csdn.net/caroline_wendy/article/details/28614491string模板(template)参考: http:/
2023-01-31

python 定制windows 开机启

最近发现电脑开机速度越来越慢了。准备用python写一个开机启动的小程序:1:开机后等待12s等待网络连接,之后判断网络,如果还是连接不上,就放弃开机启动的项目。1:判断开机的日期,如果是周六日的时候就不用开启工作时候的程序了。startu
2023-01-31

Python如何自定义元类

这篇文章主要介绍了Python如何自定义元类,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1、说明一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用
2023-06-14

python怎么定义类属性

在 python 中定义类属性用于存储与类自身相关的信息,语法为:class myclass: class_attribute = value。可通过类名或实例名(需加上类名前缀)访问和修改类属性。实例属性与类属性的区别在于作用域、默认值和
python怎么定义类属性
2024-05-22

python类方法怎么定义

本篇内容介绍了“python类方法怎么定义”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!定义1、类方法的定义需要借助于装饰器。2、在定义类方
2023-06-30

Python 自定义类的排序

Python 里面自定义类的时候, 一般需要重写几个方法, __init__ 一般是构造函数这里面有一个__cmp__() 是比较函数, 重写它的时候,一定要记得返回值有三个,0,±1  !! 而不是返回0,1   这里没有注意,导致在排序
2023-01-31

如何限制特定类型的接口{}

问题内容我正在使用 go,并且有一个工厂函数,它根据请求的标识符返回不同类型的对象:func newobject(id string) interface{} {switch id {case "truck":return truck{
如何限制特定类型的接口{}
2024-02-06

python类的继承怎么定义

这篇文章主要介绍“python类的继承怎么定义”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“python类的继承怎么定义”文章能帮助大家解决问题。说明1、基于一个现有的类来获得它所有的能力,并以此来
2023-06-30

Python 定义自己的常量类

在实际的程序开发中,我们通常会将一个不可变的变量声明为一个常量。在很多高级语言中都会提供常量的关键字来定义常量,如 C++ 中的 const , Java 中的 final 等,但是 Python 语言因为变量无类型,所以也就不存在这样的修
2023-01-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录