zoukankan      html  css  js  c++  java
  • 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)) 
  • 相关阅读:
    android webview 使用以及一些异常处理及上传文件问题
    bootstrap 下拉菜单不显示的解决办法
    无损图片缩放
    startssl,免费的ssl证书申请及注意事项
    iis7.5
    vs2013 类名颜色显示黑色,无法修改
    "未能找到类型或命名空间名称",引用dll的时候出错
    由于 add 运算符中“Chinese_PRC_CI_AS”和“Chinese_PRC_CS_AS_WS”之间的排序规则冲突
    asp.net mvc int[] 和 string[] 自定义数组绑定
    windbg定位WEB性能瓶颈案例一则
  • 原文地址:https://www.cnblogs.com/ifyoushuai/p/9140265.html
Copyright © 2011-2022 走看看