Python的动态性

一、动态属性与__slots__
python对象可以动态的添加方法,但是这种添加的方法仅对当前对象有效,例如:

class Cat():
	def __init__(self, name):
		self.name = name
	
	def walk_fun(self):
		print('自定义方法,名字是%s' % self.name)

c1 = Cat('aaa')
c2 = Cat('bbb')
#动态绑定方法
Cat.walk = walk_fun
c1.walk()
c2.walk()

这种添加动态方法的方式很方便,但是类可能会被后续修改,带来程序的不确定性。因此python提供__slots__方法来限制可添加的动态属性和方法

class Cat():
	#限制可添加的属性方法
	__slots__ = ('walk', 'name')
	def __init__(self, name):
		self.name = name

c1 = Cat('aaa')
#绑定方法
from types import MethodType
c1.walk = MethodType(lambda self: print('自定义方法,名字是%s' % self.name), c1)
c1.walk()
#c1.age = 22 #报未知属性错误

__slots__仅限制对象添加动态属性和方法,依然可以通过类直接动态添加属性和方法,同时__slots__对派生字类也不起作用。

二、使用type()函数定义类
type(className, (class1, class2, …), dict(key1 = fun, key2 = name, …))函数定义类有三个参数:
参数一:创建的类名。
参数二: 该类继承的父类集合。由于Python 支持多继承,因此此处使用元组指定它的多个
父类。即使实际只有一个父类, 也需要使用元组语法(必须要多一个逗号〉。
参数三: 该宇典对象为i豆类绑定的类变量和方法。其中字典的key 就是类变量或方法名,

def walk_fun(self):
	print('走路')
	
#定义Cat类,并定义walk方法和name属性,注意继承的object后加逗号
Cat = type('Cat', (object,), dict(walk = walk_fun, name = 'aa'))
c = Cat()
c.walk()
print(c.name)

三、使用mateclass
当希望某一些类具有某种相同特性时,可以使用mateclass动态修改类定义,mateclass需要
继承type类并重写__new__()方法,例如实时计算商品总价的类:

#继承type类
class TatolPriceClass(type):
	def __new__(cls, name, bases, attrs):
		#动态添加总价格
		attrs['tatol_price'] = lambda self: self.price * self.discount
		return type.__new__(cls, name, bases, attrs)

class Product1(metaclass = TatolPriceClass):
	__slots__ = ('name', 'price', '__discount')
	def __init__(self, name, price):
		self.name = name
		self.price = price

	@property
	def discount(self):
		return self.__discount
	
	@discount.setter
	def discount(self, discount):
		self.__discount = discount

class Product2(metaclass = TatolPriceClass):
	__slots__ = ('name', 'price', '__discount')
	def __init__(self, name, price):
		self.name = name
		self.price = price

	@property
	def discount(self):
		return self.__discount
	
	@discount.setter
	def discount(self, discount):
		self.__discount = discount

p1 = Product1('商品1', 12)
p2 = Product2('商品2', 10)
p1.discount = 2
p2.discount = 3
#调用总计计算方法
print(p1.tatol_price(), p2.tatol_price())

上例利用mateclass动态修改类定义,使得Product1和Product1这两个类同时拥有了计算商品总价的能力,如果计算方式发生变化,只需要修改TatolPriceClass即可。

你可能感兴趣的:(python笔记)