Python面向对象编程

类定义

class ClassName(object):
"""docstring for ClassName"""
def __init__(self, arg):
    super(ClassName, self).__init__()
    self.arg = arg

def method(self, args):
   pass

Python中的类也是一个对象,类与其实例拥有不同级别的作用域.

当试图通过实例访问一个属性时,Python会先在实例的作用域中搜索该属性,若实例作用域中不存在该属性则继续搜索类作用域.

若在类作用域中找到了该属性,Python将把这个属性复制一个副本(浅拷贝),加入到对象的作用域中。

通常我们在类中直接定义方法, 在初始化方法中__init__中定义并初始化属性.

Python中没有this参数,self是表示对象自身引用的关键字(即其它语言中的this).

定义方法时需要显式声明self参数作为第一个参数,使用Object.method()调用类方法时self不必显式传递,python将自动传递.

在类方法中访问对象属性或调用方法时需要显式使用self,否则将被解释为访问同名的方法局部变量(Python在访问对象前是无需声明的)。

类的私有属性或方法以两个下划线__开头,只允许类内部访问不允许类外访问. 公有属性或方法禁止以两个下划线开头。

采用两个下划线开头和结尾的方法一般为特殊方法,除非重写这些方法否则不要占用这些标识符。

  • __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()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值