class ClassName(object): """docstring for ClassName""" def __init__(self, arg): super(ClassName, self).__init__() self.arg = arg def method(self, args): pass
Python中的类也是一个对象,类与其实例拥有不一样级别的做用域.java
当试图经过实例访问一个属性时,Python会先在实例的做用域中搜索该属性,若实例做用域中不存在该属性则继续搜索类做用域.python
若在类做用域中找到了该属性,Python将把这个属性复制一个副本(浅拷贝),加入到对象的做用域中。sql
一般咱们在类中直接定义方法, 在初始化方法中__init__
中定义并初始化属性.数据库
Python中没有this参数,self是表示对象自身引用的关键字(即其它语言中的this).app
定义方法时须要显式声明self参数做为第一个参数,使用Object.method()
调用类方法时self没必要显式传递,python将自动传递.框架
在类方法中访问对象属性或调用方法时须要显式使用self,不然将被解释为访问同名的方法局部变量(Python在访问对象前是无需声明的)。函数
类的私有属性或方法以两个下划线__
开头,只容许类内部访问不容许类外访问. 公有属性或方法禁止以两个下划线开头。this
采用两个下划线开头和结尾的方法通常为特殊方法,除非重写这些方法不然不要占用这些标识符。编码
__init__
方法是类的构造函数,在生成对象时调用;设计
__del__
为析构函数,释放对象时使用完成清理工做
__repr__
相似java中的toString方法,用于显示对象时将对象转换为可显示的形式(通常为字符串)。
class SubClass(BaseClass1, BaseClass2): pass
须要注意圆括号中基类的顺序。再调用方法时首先调用本类方法,而后搜索基类方法。调用方法或访问属性时本类采用self,基类则使用括号中基类的名字指定。
Python中还提供了super()
来解决多重继承问题,直接用类名调用父类方法在使用单继承的时候没问题,可是若是使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。super机制里能够保证公共父类仅被执行一次,执行的顺序由__mro__
决定。
class SubClass(Baseclass): def __init__(*args): super(SubClass, self).__init__(args)
如果基类中有相同的方法名,而在子类使用时未指定,Python从左至右搜索 即方法在子类中未找到时,从左到右查找基类中是否包含方法。
class circle: radium = 0 def area(self): return math.pi * self.radium ** 2 class cylinder(circle): height = 0 def volume(self): c = circle() c.radium=1 return c.area() * self.height
“鸭子类型”是动态面向对象语言设计中的一个概念,即若是一个东西行走像鸭子,游泳像鸭子,进食像鸭子那它就是鸭子
即一个对象具备某一类的特征,便可做为该类实例来对待,没必要强制实现接口.
Python容许重写某些特殊方法来定义使用某些操做符
能够经过重写某些方法模拟字典和列表的行为:
__setitem__
按照key为元素赋值
__getitem__
按照key取元素
__delitem__
按照key删除元素
__call__
容许将对象做为函数进行调用
__len__
得到长度,调用len(obj)时即调用obj.__len__()
__iter__()
返回iterable, for-in循环会调用这个对象的next()方法进行迭代
__call__
重载函数调用,调用obj(args)
即调用obj.__call__(args)
模拟dict:
class MyDict: def __init__(self): self.data = dict() def __getitem__(self, key): return self.data.get(key) def __setitem__(self, key, val): self.data[key] = val def __delitem__(self, key): self.data.pop(key) def __iter__(self): for item in self.data: yield item def __len__(self): return len(self.data) if __name__ == '__main__': d = MyDict() # set item d['first'] = 1 d['second'] = 2 # get item print(d['first'], d['second']) # len print(len(d)) # iter for item in d: print(item) # del item del(d['first']) print(d['first'])
模拟list:
class MyList: def __init__(self): self.data = list() def __getitem__(self, key): return self.data[key] def __setitem__(self, key, val): self.data[key] = val def __delitem__(self, key): self.data.pop(key) def __iter__(self): for item in self.data: yield item def __len__(self): return len(self.data) if __name__ == '__main__': l = MyList() l.data.extend([0,0]) # set item l[0] = 1 l[1] = 2 # get item print(l[0], l[1]) # len print(len(l)) # iter for item in l: print(item) # del item del(l[0]) print(l[0])
做为函数:
class MyFunc(): def __call__(self): print('I am callable') if __name__ == '__main__': f = MyFunc() f()
重载算术与关系运算:
__cmp__
比较运算
__add__
加运算
__sub__
减运算
__mul__
乘运算
__div__
除运算;
__mod__
求余运算
__pow__
乘方
Python中类的类型为"type",type()函数能够创建一个"type"类型对象即一个类。type函数有三个参数,class的名称,基类元组和成员名-成员对象字典。
def func(args): print("fuck"); ClassObj = type('ClassName',(object,),dict(method1=func)) print(ClassObj) print(dir(ClassObj))
Python的class语法其实是调用type()函数进行动态编译。元类metaclass是进行类动态建立与修改的另外一种方式。
def func(args): pass class aMetaclass(type): def __new__(classObj, className, bases, attrs): attrs.update(dict(aMethod=func)); return type.__new__(classObj,className,bases,attrs) class aClass(object, metaclass=aMetaclass): pass obj = aClass(); print(dir(obj))
一般类的建立由type()
或type.__new__()
完成,在指定了一个类的metaclass参数以后,该类对象的建立将交由metaclass来完成。metaclass.__new__
将会拦截类的建立,进行处理后调用type.__new__
进行建立。
相对于使用type()动态建立类,metaclass可使用继承等OOP机制且做为类其功能比函数更为强大。metaclass拥有其它成员和类动态添加成员机制,而函数只能以硬编码编制建立逻辑。
示例,使用metaclass编写ORM:
ORM(Object Relational Mapping,对象-关系映射)把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码更简单,不用直接操做SQL语句。要编写一个ORM框架,全部的类都只能动态定义,由于只有使用者才能根据表的结构定义出对应的类来。
tinyORM中首先定义了表中域的类型,而后定义Model类执行建立数据表的逻辑,类Users定义数据表'users'。
Users类建立时首先封装建立类的参数,而后封装Model的建立参数执行基类Model的建立。Model建立过程被ModelMetaclass.__new__
拦截,传入的name参数为'users'(__new__
只处理Model派生类的创建,对Model类的创建不进行处理)。
__new__
将一个成员映射为一列,并存入__mapping__
中和保存数据表名字的__table__
一块儿添加到Users的属性中。__new__
返回修改后的类, 执行Model.__init__
进行初始化。
#tinyORM.py #Define field types class Field(object): def __init__(self, name, column_type): self.name = name self.column_type = column_type def __repr__(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') #define Model class ModelMetaclass(type): def __new__(cls, name, bases, attrs): if name=='Model': return type.__new__(cls, name, bases, attrs) print('Found model: %s' % name) mappings = dict() for k, v in attrs.items(): if isinstance(v, Field): print('Found mapping: %s ==> %s' % (k, v)) mappings[k] = v for k in mappings.keys(): attrs.pop(k) attrs['__mappings__'] = mappings # save mapping of attribute-column attrs['__table__'] = name # name the table after the class name 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): try: return self[key] except KeyError: raise AttributeError(r"'Model' object has no attribute '%s'" % key) def __setattr__(self, key, value): self[key] = value def save(self): fields = [] params = [] args = [] for k, v in self.__mappings__.items(): 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)) #send sql and args to database #The end of ORM, the following code should be created by ORM's users. #define table 'user' and its structure class Users(Model): # 定义类的属性到列的映射: id = IntegerField('id') name = StringField('username') password = StringField('password') def test() u = Users(id=2333, name='username', password='password') u.save() test()