Python面向对象编程

类定义

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__ 乘方

metaclass

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()
相关文章
相关标签/搜索