• 面向对象二


    一.元类(type)

    type元类又称构建类

    python中一切皆对象,类也是一个对象。python中大多数内置的类(包括object)以及自己定义的类,都是由type元类创造的。

    1.type获取对象从属的类

    # 以下三种方法得到各自从属的类str、list、tuple
    print(type('123'))    #<class 'str'>
    print(type([1,2,3]))  #<class 'list'>
    print(type((1,2,3)))  #<class 'tuple'>
    
    #str、list、tuple都是源码中的类,同属于type元类
    print(type(str))      #<class 'type'>
    print(type(list))     #<class 'type'>
    print(type(tuple))    #<class 'type'>
    

    2.type和object的关系

    object是所有类的父类(包含type类),type元类可以实例化成所有类(包含object)。总的来说,object实例化对象,type实例化类

    # object类是type类的一个实例
    print(type(object))   #<class 'type'>
    
    # object类是type类的父类
    print(issubclass(type,object))   # True
    

    Top

    二.反射

    反射是程序对自己内部代码的一种自省方式。

    python面向对象中的反射:通过字符串的形式操作对象相关的属性。(python中一切事物都是对象,都可以使用反射)

    下面通过四种方式实现代码自省(反射)

    1.对对象的反射

    class A:
        country = "中国"
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def func(self):
            print("in A func")
            
    obj = A("alex",11)
    print(hasattr(obj,"name"))           # True 判断obj对象是否有name属性
    print(getattr(obj,"age",None))       # 11   得到obj的age属性,默认得到None
    getattr(obj,"func")()
    setattr(obj,"name","wusir")
    delattr(obj,"name")
    

    2.对类的反射

    class A:
        country = "中国"
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def func(self):
            print("in A func")
    
    print(hasattr(A,'country'))          # True
    getattr(A,"func")(1)   
    

    3.从其他模块

    # module_test.py
    def test():
        print("from the test")
    
        
    # index.py
    import module_test as obj
    
    print(hasattr(obj,'test'))     # True
    getattr(obj,"test")()          # 打印 from the test
    

    4.从当前模块

    import sys
    def func():
        print("func")
    
    current_modules = sys.modules[__name__]   # 得到当前文件这个模块
    hasattr(current_modules,"func")           # True 
    getattr(current_modules,"func")()         # 打印func
    

    Top

    三.函数和方法的区别

    函数都是显性传参,方法都是隐形传参(谨记)

    以下有两种方法区分方法和函数:

    1.打印函数名

    通过类名调用类中的实例方法叫做函数

    通过对象调用类中的实例方法叫方法

    def func1():
        pass
    
    class A:
        def func(self):
            pass
    
    print(func1)        # <function func1 at 0x000001B5A5A0A8C8>
    print(A.func)       # <function A.func at 0x000001B5A5A0A950>    
    obj = A()
    print(obj.func)     # <bound method A.func of <__main__.A object at 0x000001B5A5A084A8>>
    

    类中的静态方法其本质就是函数,类中的类方法就是方法

    class A:
        @staticmethod
        def func1():
            pass
        @classmethod
        def func2(cls):
            pass
    
    
    print(A.func1)     # <function A.func1 at 0x000002D6FD10A9D8>
    a = A()
    print(a.func1)     # <function A.func1 at 0x000002D6FD10A9D8>
    print(A.func2)     # <bound method A.func2 of <class '__main__.A'>>
    print(a.func2)     # <bound method A.func2 of <class '__main__.A'>>
    

    2.借助模块判断

    FunctionType 判断是否是函数
    MethodType 判断是否是方法

    from types import FunctionType
    from types import MethodType
    
    def func():
        pass
    class A:
        def func(self):
            pass
    obj = A()
    
    print(isinstance(func,FunctionType))
    print(isinstance(A.func,FunctionType))
    print(isinstance(obj.func,FunctionType))
    print(isinstance(obj.func,MethodType))
    
    

    Top

    四.特殊的双下方法

    双下方法是特殊方法,是由python解释器提供的。

    不同的双下方法有不同的触发方式。

    1.len

    len('alex')      # 自动执行'alex'所属类(str)的__len__方法
    len([1,2,3])     # 自动执行[1,2,3]所属类(list)的__len__方法
    
    class B:
        def __len__(self):
            return 666
    b = B()
    len(b)            # 自动执行对象b所属类B的__len__()方法
    
    

    2.hash

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __hash__(self):
            return hash(str(self.a) + str(self.b))
    a = A()
    hash(a)   # 自动执行a的所属类A的__hash__方法   
    
    

    3.str

    在打印对象或者str()方法时,自动执行对象所属类的__str__方法

    class A:
        def __init__(self):
            pass
        def __str__(self):
            return '太白'
    a = A()
    print(a)     # 自动执行a所属类A的__str__方法
    
    

    4.repr

    repr()执行对象所属类中的__repr__方法,返回对象的原有形态

    class A:
        def __init__(self):
            pass
        def __repr__(self):
            return '太白'
    a = A()
    repr(a)      # 自动执行a所属类A的__repr__方法
    
    

    5.call

    对象(),自动触发执行对象从属类的__call__方法

    class Foo:
        def __init__(self):
            pass
        
        def __call__(self, *args, **kwargs):
            print("__call__")
    
    obj = Foo()
    obj()     # 打印 __call__
    # 如果类中没有__call__方法,报错:TypeError: 'Foo' object is not callable
    

    6.eq

    class A:
        def __init__(self):
            self.a = 1
        def __eq__(self, other):
            if self.a == other.a:
                return True
    x = A()
    y = A()
    print(x == y)  # 自动执行x和y从属类A的__eq__方法,将x传给self,y传给other
    

    7.del

    析构方法。(python中的垃圾回收机制,程序执行完,自动回收)

    class A:
        def __del__(self):
            print(666)
    obj = A()      # 执行完自动执行obj所属类A的__del__方法
    

    8.new

    class A:
        def __init__(self):
            self.x = 1
            print("in init function")
    
        def __new__(cls, *args, **kwargs):
            print("in new function")
            return object.__new__(A)           # 必须要有此行代码,不然对象()只会执行__new__方法,不执行__init__方法
    a = A()
    
    # 类名()
    '''
    1.先触发object类的__new__方法,此方法在内存中开辟一个对象空间
    2.执行__init__的方法
    '''
    

    9.__item__系列

    对象如果以字典形式出现,自动触发item系列中的方法。

    class Foo:
        def __init__(self,name):
            self.name = name
    
        def __getitem__(self, item):    # self=f1 item='age'
            print(self.__dict__)
    
        def __setitem__(self, key, value): # self=f1 key='age1' value=18
            self.__dict__[key] = value
    
        def __delitem__(self, key):  # self=f1 key='age1'
            print(key)
    
        def __delattr__(self, item): # self=f1 item='age'
            print(item)
    
    f1 = Foo('sb')
    f1['age']         # 执行__getitem__()
    f1['age1'] = 18   # 执行__setitem__()
    del f1['age1']    # 执行__delitem__()
    del f1.age        # 执行__delattr__(),父类如果没有__delattr__()方法,会执行object中的,真的删除
    

    10.上下文管理器相关

    对于自己定义的类,如果想使用with statment方法,必须要在类中添加__enter__()和__exit__()两方法,缺一不可。

    这种例子会报错:

    class A:
        def __init__(self,text):
            self.text = text
    with A("打印") as f:
        print(f.text)
    
    

    类中添加__enter__()和__exit__()方法后不会报错

    class A:
        def __init__(self,text):
            self.text = text
    
        def __enter__(self):                    # 开启上下文管理器对象时触发此方法
            self.text = self.text + "您来了"
            return self                         # 固定写法,返回self
    
        def __exit__(self, exc_type, exc_val, exc_tb):    # 执行完上下文管理器对象f触发此方法
            self.text = self.text + "这就走了"
    
    with A("大爷") as f:
        print(f.text)            # 大爷您来了
    print(f.text)                # 大爷您来了这就走了
    

    11. iter

    class A:
        def __init__(self,name):
            self.name = name
        def __iter__(self):
            yield 10
    
    obj = A("alex")
    for i in obj:         # for循环obj,自动执行类A中的__iter__()方法,有__iter__()方法,使得obj为可迭代对象。
        print(i)
    

    五.单例模式

    所有实例化对象公用一个内存地址。
    好处:节省内存

    class A:
        __instance = None
    
        def __init__(self,name):
            self.name = name
    
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance = object.__new__(cls)
            return cls.__instance
    
    obj = A("alex")
    print(obj)             # <__main__.A object at 0x0000014B366A8470>
    obj1 = A("wusir")
    print(obj1)            # <__main__.A object at 0x0000014B366A8470>
    
  • 相关阅读:
    prototype 和function关系等总结
    js作用域的几个问题
    关于对象引用的作用域
    深刻理解下js的prototype
    如何判断一个对象是数组
    理解js的几个关键问题(2): 对象、 prototype、this等
    更新触发器
    sql事物和try catch
    图片与base64编码互换
    UCML点击BPO报异常
  • 原文地址:https://www.cnblogs.com/luckinlee/p/11620357.html
Copyright © 2020-2023  润新知