Python初探第四篇-面向对象进阶

一,反射

  反射即在类的外部访问或者修改对象的属性,可以通过Python内置的四个函数来操作

class Foo:
    def __init__(self, name):
        self.name = name
        # def method(self):
        #     print("this is a method")


if __name__ == '__main__':
    f = Foo("abc")
    if hasattr(f, "name"):  #获取 有则为True
        print(getattr(f, "name"))  # 获取对象的属性或者方法
    else:
        setattr(f, "name", "abc")  # 设置

    if hasattr(f, "method"):
        func = getattr(f, "method")
        func()
    else:
        setattr(f, "func", lambda: print("aaaa"))  # 设置方法
        f.func()
    delattr(f, "name")  # 删除
    print(f.__dict__)  # {'func': <function <lambda> at 0x0000000002718950>},成功删除 "name"

二,自定制对象的显示格式

class Foo:
    def __init__(self, name):
        self.name = name
      
    def __str__(self):
        return self.name #将对象的某个属性作为打印对象时的输出

三,自定制调用实例方法 

class Foo(object):
    def func(self):
        print('hello')

    def __setitem__(self, key, value):
        print('__setitem__')
        self.__dict__[key] = value

    def __getitem__(self, item):
        print('__getitem__')
        if item in self.__dict__:
            return self.__dict__[item]
        elif item in Foo.__dict__:
            return Foo.__dict__[item]
        else:
            raise ValueError

    def __setattr__(self, key, value):
        print('__setattr__')
        self.__dict__[key] = value

    def __delattr__(self, item):
        print('__delattr__')

    def __delitem__(self, key):
        print('__delitem__')


f = Foo()
func = f['func']  # __getitem__
f['func1'] = lambda: print('hello 1')  # __setitem__
f.func2 = lambda: print('hello 2')
f.func1()  # hello 1
f.func2()  # hello 2
del f['func']  # _delitem__
del f.func  # __delattr__

""""
__setattr__ , __delattr 和 __setitem__ , delitem__区别是如果通过f.来修改则使用前者,
f["xxx"] 来操作访问,则使用后者,__getitem__通过f["xxx"] 访问时触发
"""
View Code

四,上下文管理协议

      当一块代码执行完之后会自动释放,保存资源,如打开一个文件,申请一个线程,打开数据库等待。这就是上下文管理。在Python中用with..as..语法来实现

with open('a.txt','rb') as f:
    info = f.read()

  自定制类,使该类的实例对象也能实现上下文管理

class Open():
        def __init__(self,filename,mode):
            self.obj = open(filename,mode)
        def write(self):
            pass
        def __enter__(self):         #必须实现的方法,赋值给as 后的元素
            return self.obj
        def __exit__(self, exc_type, exc_val, exc_tb): #必须实现的方法,自动退出
            return True

with Open('111.txt','rb') as f:
        print(f.read())

五,迭代器对象

  给外界提供了一种对对象的遍历方法,类中需要实现__iter__方法,__next__方法

class Foo:
    def __init__(self, n):
        self.n = n

    def __iter__(self):  # 用于返回一个可迭代对象
        return self

    def __next__(self):
        if self.n > 10:
            raise StopIteration  # 必须抛出异常,终止迭代
        else:
            self.n += 1
            return self.n


f = Foo(0)
for i in f:
    print(i)

  

六,描述符理论

  定义:python描述符是一个“绑定行为”的对象属性,在描述符协议中,它可以通过方法重写属性的访问。这些方法有 __get__(), __set__(), 和__delete__()。如果这些方法中的任何一个被定义在一个对象中,

这个对象就是一个描述符。即一个对象含有 __get__(), __set__(),或__delete__()方法

class Foo(object):
    def __int__(self):
        pass

    def __get__(self, instance, owner):
        print("__get__")

    def __set__(self, instance, value):
        print("__set__")

    def __delete__(self, instance):
        print("__delete__")

class Test(object):
    name = Foo()

    def __init__(self,name):
        self.name = name   #1, __set__
    def display(self):
        return self.name


t=Test('bokeyuan')
t.name            #2,__get__
t.name = 'aaa'   #3 __set__
del t.name      #4 __delete__

  描述符有两种:

    1,数据描述符(实现了__get__()和__set__()方法)

    2,非数据描述符(仅仅实现了__get__()方法)

  对于以上可以这样理解:当通过实例为某个变量(对象)赋值时,如 self.name = 'aaa'时。

    若name是非数据描述符时,即没有__set__方法,就只能调用实例属性字典来设置值,实例属性将覆盖非数据描述符,之后对name操作与非数据描述符无关。

     若name为数据描述符对象时,因为其所属的类实现了get和set方法,因而比实例属性有更高的优先级,那么对实例的属性操作,触发的都是描述符的。

  而官方文档对于描述符还有一个规定,类属性优先级高于数据描述符,即通过类本身为类设置属性时不会触发描述符。

  因为可以得出关于描述符的优先级

    1.类属性
    2.数据描述符
    3.实例属性
    4.非数据描述符
    5.找不到的属性触发__getattr__()

      应用示例:自定制实现@propety

class Property(object):
    def  __init__(self,func):
        self.func = func

    def __get__(self, instance, owner):
        return self.func(instance)

class Foo(object):
    def __init__(self,name):
        self.__name = name

    @Property  #name = Property(name) 装饰器
    def name(self):
        return self.__name

f=Foo('bokeyuan')
print(f.name)

  实现@classmethod:

class Classmethod(object):
    def __init__(self,func):
        self.func = func
    def __get__(self, instance, owner):
        def deco():
            return self.func(owner)
        return deco


class Foo(object):
    name = 'bokeyuan'
    def __init__(self,name):
        self.__name = name

    @Classmethod    #tag = classmethod(tag)
    def tag(cls):
        return cls.name

f=Foo('bokeyuan')
print(f.tag())

  实现@staticmethod

class Classmethod(object):
    def __init__(self,func):
        self.func = func
    def __get__(self, instance, owner):
        def deco():
            print(instance,owner)
            return self.func(owner)
        return deco
class Staticmethod(object):
    def __init__(self,func):
        self.func = func
    def __get__(self, instance, owner):
        def deco(*args):
            return self.func(*args)
        return deco

class Foo(object):
    name = 'bokeyuan'
    def __init__(self,name):
        self.__name = name

    @Staticmethod
    def add(*args):
        print(args)
        sum = 0
        for i in args:
            sum+=i
        return sum
f=Foo('bokeyuan')
print(f.add(1,2,3)) 

猜你喜欢

转载自www.cnblogs.com/ifyoushuai/p/9140265.html