面向对象高级编程
1、对实例进行添加或修改属性都不会影响到calss,那么其他的实例也将或不共享新加的属性,这时候我们可以通过给class绑定属性达到所有实例均可调用的效果;(这是像java静态语言很难实现的)
2、__slots__
:限制该class实例能添加的属性,只对当前的类起作用,对子类并没有用,除非在子类中也定义一个__slots__
;
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
3、@property
:把一个方法变成属性调用当一个属性调用时实际上转化成了get_name();
@name.setter
:调用属性时实际转化成了set_name();
访问时直接实例名.属性名即可;赋值时调用的就是set方法没有的时候调用的get方法
多重继承(java里面是没有多重继继承的接口能达到伪多重继承的效果)
class Mammal(Animal):
pass
class Runnable(object):
def run(self):
print('Running...')
class Flyable(object):
def fly(self):
print('Flying...')
class Dog(Mammal, Runnable):
Pass
class Bat(Mammal, Flyable):
pass
Mixln(多重继承设计)
定制类
1、__str__
类似于java的toString()
功能,但若使用print则调用的不是__str__()
方法而是__repr__()
调试服务的
2、__iter__()
返回一个迭代对象;
3、__getitem__()
实现此方法后可以按下标取值;
如果要使用切片功能则只需要加一个判断代码如下:
class Fib(object):
def __getitem__(self, n):
if isinstance(n, int): # n是索引
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
if isinstance(n, slice): # n是切片
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
4、__getattr__
在没有找到属性的情况下,调用__getattr__
;
5、__call__()
方法,就可以直接对实例进行调用;
枚举类
两种定义方式:
1、属性自动赋值,默认从1开始
for name, member in Month.__members__.items():
print(name, '=>', member, ',', member.value)
2、自定义赋值Enum派生类:@unique
装饰器检查是否有重复值
from enum import Enum, unique
@unique
class Weekday(Enum):
Sun = 0 # Sun的value被设定为0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
元类
1、python是属于动态语言,而动态语言和静态语言最大的区别就是函数和累得定义不是编译时定义的,而是运行时动态创建的;
2、type()
函数既可以返回一个函数类型又可以创建出新的类型;
Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
三个参数:
a.Class的名称;
b.继承的父类集合,Python支持多继承,若只有一个父类别忘了tuple的单个元素写法;
c.Class的方法名称与函数绑定,这里我们吧函数fn绑定到方法名hello上;
3、metaclass控制类的创建行为:(很魔幻,用的少,很难)
a)先定义Metaclass,再创建类,最后创建实例;
b)四个参数: 当前准备创建的类的对象; 类的名字; 类继承的父类集合; 类的方法集合。
# metaclass是类的模板,所以必须从`type`类型派生:class ListMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
return type.__new__(cls, name, bases, attrs)