🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 面向对象 ## 多重继承、定制类、元类 ### 动态创建类 type(classname) #类的类型就是type 因此可以看出 **类是由type函数动态创建成的** type(classobject) # 类实例的类型是 classname 类名称 type()函数既可以返回一个对象的类型,又**可以创建出新的类型** >>> def fn(self, name='world'): # 先定义函数 ... print('Hello, %s.' % name) >>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class >>> h = Hello() >>> h.hello() Hello, world. >>> print(type(Hello)) <type 'type'> >>> print(type(h)) <class '__main__.Hello'> 要创建一个class对象,type()函数依次传入3个参数: 1. class的名称; 2. 继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法; 3. class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。 > **note:** 通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class。 ### 控制类的创建行为 metaclass (元类) 我不要用type来创建类 我要用type的子类xxxxMetaclass > metaclass允许你创建类或者修改类。你可以把类看成是metaclass创建出来的"实例" > 先定义metaclass,就可以创建类,最后创建实例 # 为list添加add方法 class ListMetaclass(type): def __new__(cls,name,bases,attrs): # name 类名称 # bases 继承父类列表 # attrs 属性/方法 attrs['add'] = lambda self,value:self.append(value) # 对类属性/方法做出一些调整 return type.__new__(cls,name,bases,attrs) class MyList(list): # __metaclass__ = ListMetaclass #我不要用type来创建类 我要用type的子类 def __insert(self): # attrs 中键名是 '_MyList__insert' pass if __name__ == '__main__': L = MyList() L.add(1) L.add(2) print L # [1,2] > **使用场景举例** ORM全称“Object Relational Mapping”,即对象-关系映射,就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码更简单,不用直接操作SQL语句。 要编写一个ORM框架,所有的类都只能动态定义,因为只有使用者才能根据表的结构定义出对应的类来。 class Field(object): def __init__(self,name,column_type): self.name = name self.column_type = column_type def __str__(self): return '<%s:%s>' % (self.__class__.__name__,self.name) class StringField(Field): def __init__(self,name): super(StringField,self).__init__(name,'varchar(100)') class IntegerField(Field): def __init__(self,name): super(IntegerField,self).__init__(name,'bigint') class ModelMetaclass(type): def __new__(cls,name,bases,attrs): if name == 'Model': return type.__new__(cls,name,bases,attrs) mappings = dict() for k,v in attrs.iteritems(): if isinstance(v,Field): print 'Found mapping: %s==>%s' % (k,v) mappings[k] = v for k in mappings.iterkeys(): attrs.pop(k) attrs['__table__'] = name # 假设表名和类名一致 attrs['__mappings__'] = mappings # 保存属性和列的映射关系 return type.__new__(cls,name,bases,attrs) class Model(dict): # 继承自 字典 __metaclass__ = ModelMetaclass def __init__(self, **kw): super(Model, self).__init__(**kw) #传递过来的参数都成了字典 键值 def __getattr__(self, key): # 字典本不能 dict.key 这里实现 print 'yyyyyyyyyy' try: return self[key] except KeyError: raise AttributeError(r"'Model' object has no attribute '%s'" % key) def __setattr__(self, key, value): print 'xxxxxxxx' self[key] = value def save(self): fields = [] params = [] args = [] for k, v in self.__mappings__.iteritems(): fields.append(v.name) params.append('?') args.append(getattr(self, k, None)) sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params)) print('SQL: %s' % sql) print('ARGS: %s' % str(args)) class User(Model): # 定义类的属性到列的映射: id = IntegerField('id') name = StringField('username') email = StringField('email') password = StringField('password') if __name__ == '__main__': # 创建一个实例: u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd') print u # {'email': 'test@orm.org', 'password': 'my-pwd', 'id': 12345, 'name': 'Michael'} print u.name # yyyyyyyyyy \n Michael # 保存到数据库: #u.save() ### 定制类 参见魔术方法 > \_\_getattr\_\_ 可以类的所有属性和方法调用全部动态化处理 ### python支持多重继承 ### 类方法转换成属性访问 @property class Student(object): @property def score(self): return self._score @score.setter # 不定义setter 就是只读属性 def score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value >>> s = Student() >>> s.score = 60 # OK,实际转化为s.set_score(60) >>> s.score # OK,实际转化为s.get_score() 60 >>> s.score = 9999 Traceback (most recent call last): ... ValueError: score must between 0 ~ 100! ### 限制类能添加的属性 \_\_slots\_\_ class Student(object): \_\_slots\_\_ = ('name', 'age') # 试图绑定此未定义的属性 抛出 AttributeError异常 \_\_slots\_\_定义的属性仅对当前类起作用 在子类中也定义\_\_slots\_\_,这样,子类允许定义的属性就是自身的\_\_slots\_\_加上父类的\_\_slots\_\_ ### 为类动态添加方法 >>> from types import MethodType >>> def set_score(self, score): ... self.score = score >>> Student.set_score = MethodType(set_score, None, Student) ### 为对象动态添加方法 >>> s = Student() >>> s.set_score = MethodType(set_score, s, Student) ## 继承 多态 ### 判断 对象类型 type() # 类的类型就是type,实例的类型就是类名称 (创建类就是使用type()函数) Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class isinstance() #适用于对象类型、继承关系 ### 获取对象属性和方法 dir() getattr() 可以获取对象方法并变量调用 setattr() hasattr() ### 继承和多态 **开闭原则** . 对扩展开放 :允许新增x子类 . 对修改封闭 : 不需要修改依赖x类型的函数