杂乱的note:
添加函数
1 | class Student(object): |
为了给所有实例都绑定方法,可以给class绑定方法:
1 | def set_scorex(self, score): |
通常情况下,上面的set_score方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。
如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性
Python允许在定义class的时候,定义一个特殊的slots变量,来限制该class实例能添加的属性:
1 | class Student(object): |
使用slots要注意,slots定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
property装饰器
Python内置的@property装饰器就是负责把一个方法变成属性调用。
1 | class Student(object): |
上面的类方法中,在对属性_score进行设置操作时进行了限制检查,规定value必须是数字同时限制范围,否则就抛出Error。
1 | s = Student() |
上面的调用方法又略显复杂,没有直接用属性这么直接简单,此时就可以祭出@property装饰器
1 | class Student(object): |
str
我们先定义一个Student类,打印一个实例:
1 | class Student(object): |
打印出一堆<main.Student object at 0x109afb190>,不好看。
怎么才能打印得好看呢?只需要定义好str()方法,返回一个好看的字符串就可以了:
1 | class Student(object): |
此时直接敲变量不用print,打印出来的实例还是不好看:
1 | s = Student('Michael') |
这是因为直接显示变量调用的不是str(),而是__repr__()
,两者的区别是str()返回用户看到的字符串,而repr()返回程序开发者看到的字符串,也就是说,repr()是为调试服务的。
解决办法是再定义一个repr()。但是通常str()和repr()代码都是一样的,所以,有个偷懒的写法:
1 | class Student(object): |
iter
如果一个类想被用于for … in循环,类似list或tuple那样,就必须实现一个iter()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环
1 | class Fib(object): |
getitem
为了实现通过下标访问元素,需要增加getitem()方法:
1 | def __getitem__(self, item): |
为了为当前类添加切片功能(类似列表序列的list[1,5]),我们需要改写下getitem()方法:
1 | def __getitem__(self,n): |
- 通过重写call()方法,通过实例自身的调用,达到()调用的效果
1 | class Student(object): |
枚举类Enum
python中的枚举类中,每个我们规定的常量都是唯一实例。
1 | from enum import Enum |
枚举派生类
为了更方便的操作枚举类型数据,我们可以定义一个继承自Enum.class的子类
1 | from enum import Enum, unique |
上面实例中,导入enmu模块中的Enum和unique后,我们可以使用@unique标记对继承自Enum的子类进行元素唯一性检测,当不同的元素被设置成为相同的value,会报错
可以使用多种访问方法:
1 | day1 = Weekday.Mon |
metaclass
元类:python语言在发展中借鉴了smalltalk的思想,所有东西都是对象,类也是对象。元类就是创建类的模板,也就是说,元类就是创建类的类。正常情况下类都是采用pyhton内建的元类type来创建类这个对象,但是当我们在定义类的过程中,我们可以指定使用的元类创建我们的对象。这个元类继承自type。
1 | #a是一个对象,a.__class__指的是对象所属的类,而这个所属类所属的类呢,就是type |
通常我们第一一个类,然后实例化类的对象,我们都是希望对象能够按照类模板进行创建,而恰恰元类就是我们在创建类的过程中动态修改类的一个方法。
可以在写一个类的时候为其添加metaclass属性:
1 | class Foo(object): |
如果你这么做了,Python就会用元类来创建类Foo.你首先写下class Foo(object),但是类对象Foo还没有在内存中创建。Python会在类的定义中寻找metaclass属性,如果找到了,Python就会用它来创建类Foo,如果没有找到,就会用内建的type来创建这个类
1 | class Foo(Bar): |
Foo中有metaclass这个属性吗?如果是,Python会在内存中通过metaclass创建一个名字为Foo的类对象(我说的是类对象,请紧跟我的思路)。如果Python没有找到metaclass,它会继续在Bar(父类)中寻找metaclass属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到metaclass,它就会在模块层次中去寻找metaclass,并尝试做同样的操作。如果还是找不到metaclass,Python就会用内置的type来创建这个类对象
我们可以在metaclass中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东东都可以。
type可以像这样工作
type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
我们先从一个小例子观测metaclass的功能:
1 | def upper_attr(future_class_name,future_parent,future_class_attr): |
- 使用一个真正的class当做元类
1 | class UpperAttrMetaclass(type): |