zoukankan      html  css  js  c++  java
  • 元类type 反射 函数与方法 双下方法

    1.元类type

    type  获取对象从属于的类
    
    	python 中 一切皆对象, 类在某种意义上也是一个对象, python中自己定义的类, 以及大部分内置类, 都是由type元类(构建类)实例化得来的
    

    type 与 object 的关系

    print(type(object)) 
    object类是type类的一个实例
    object类是type类的父类
    

    2.反射

    ​ 程序对自己内部代码的一种自省方式

    反射是什么

    ​ 通过字符串去操作对象的方式

    具体方法

    hasattr
    getattr
    setattr
    delattr
    

    反射角度

    实例对象

    # obj = A('赵海狗',47)
    class A:
        country = "中国"
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def func(self):
            print("in A func")
    
    obj = A("赵海狗", 47)
    
    print(hasattr(obj,"name"))
    print(hasattr(obj,"country"))
    print(hasattr(obj,"func"))
    
    print(getattr(obj,"name"))
    print(getattr(obj,"country"))
    f = getattr(obj,"func")
    f()
    print(getattr(obj, "sex", None))
    
    obj.sex = "公"
    setattr(obj, "sex", "公")
    print(obj.__dict__)
    
    delattr(obj,"name")
    print(obj.__dict__)
    

    class A:
        country = "中国"
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def func(self):
            print(self)
            print("in A func")
    
    if hasattr(A,"country"):
        print(getattr(A, "country"))
    if hasattr(A, "func"):
        obj = A("赵海狗", 26)
        getattr(obj, "func")()
        # 和下方方法一样 区别在于一个对象反射,一个类反射,一个不用传参, 一个需要传参
        getattr(A, "func")(obj)
    

    本模块

    a = 666
    def func1():
        print("in 本模块这个对象")
    
    import sys
    print(sys.modules[__name__])
    print(getattr(sys.modules[__name__], "a"))
    getattr(sys.modules[__name__], "func1")()
    
    练习题
    1.使用反射依次调用所有函数
    
    def func1():
        print("in func1")
    def func2():
        print("in func2")
    def func3():
        print("in func3")
    def func4():
        print("in func4")
    
    import sys
    func_lst = [f"func{i}" for i in range(1,5)]
    for func in func_lst:
        getattr(sys.modules[__name__], func)()
        
    2.使用反射做出一个注册登录系统
    
    class User:
        user_list = [("login", "登录"),("register", "注册"),("save", "存储")]
    
        def login(self):
            print("欢迎来到登录页面")
        def register(self):
            print("欢迎来到注册页面")
        def save(self):
            print("欢迎来到存储页面")
    
    while 1:
        choose = input("请输入序号: 
    : 登录
    2: 注册
    3: 存储
    ").strip()
        obj = User()
        getattr(obj, obj.user_list[int(choose)-1][0])()
    
    

    其他模块

    tbjx文件
    name = "太白金星"
    def func():
        print("in tbjx func")
    
    class C:
        area = "北京"
        def __init__(self, name):
            self.name = name
        def func(self):
            print("in B func")
    
    import tbjx
    print(getattr(tbjx,"name"))
    getattr(tbjx, "func")()
    
    import tbjx
    # 1. 找到tbjx对象 的C类,实例化一个对象.
    obj = getattr(tbjx, "C")("太白金星")
    print(obj.__dict__)
    # 2. 找到tbjx对象 的C类,通过对C类这个对象使用反射取到area.
    f = getattr(getattr(tbjx, "C"), "area")
    print(f)
    # 3. 找到tbjx对象 的C类,实例化一个对象,对对象进行反射取值.
    print(getattr(obj, "name"))
    

    3.函数与方法

    通过打印函数名的方式区别方法和函数

    def func1():
        pass
    class A:
        def func(self):
            pass
    
    # 通过类名调用的类中的实例方法叫做函数
    print(func1)
    print(A.func)
    
    # 通过对象调用的类中的实例方法叫方法
    obj = A()
    print(obj.func)
    

    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))
    """
    True
    True
    False
    True
    """
    

    总结

    ​ python 中一切皆对象, 类在某种意义上也是一个对象, python中自己定义的类, 以及大部分内置类, 都是由type元类(构建类)实例化得来的

    ​ python 中一切皆对象, 函数在某种意义上也是一个对象,函数这个对象是从FunctionType这个类实例化出来的

    ​ python 中一切皆对象, 方法在某种意义上也是一个对象,方法这个对象是从MethodType这个类实例化出来的

    如何判断方法还是函数

    ​ 函数都是显性传参, 方法都是隐性传参

    4.特殊的双下方法

    特殊的双下方法:

    ​ 原本是开发python这个语言的程序员用的, 源码中使用的

    ​ 双下方法: 你不知道你干了什么就触发某个双下方法

    __len__

    class B:
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def __len__(self):
            print(self.__dict__)
            return len(self.__dict__)
    
    b = B("liye", 28)
    print(len(b))
    """
    {'name': 'liye', 'age': 28}
    2
    """
    print(len({"name": "leye", "age":28}))
    """
    2
    """
    # len()就会触发__len__方法
    

    __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()
    print(hash(a))
    """
    -855395274340638840
    """
    

    __str__ ***

    class A:
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def __str__(self):
            print(666)
            return (f"姓名:{self.name} 年龄:{self.age}")
    
    a = A("赵海狗", 35)
    b = A("李业", 56)
    c = A("华丽", 18)
    print(f"{a.name}{a.age}")
    print(f"{b.name}{b.age}")
    print(f"{c.name}{c.age}")
    """
    赵海狗35
    李业56
    华丽18
    """
    
    # 打印对象触发__str__方法
    print(a)
    print(b)
    print(c)
    """
    666
    姓名:赵海狗 年龄:35
    666
    姓名:李业 年龄:56
    666
    姓名:华丽 年龄:18
    """
    
    # 直接str转化也可以触发
    print(str(a))
    """
    666
    姓名:赵海狗 年龄:35
    """
    

    __repr__

    class A:
    
        def __init__(self,name,age):
            self.name = name
            self.age =age
    
        def __repr__(self):
            print(666)
            return f'姓名: {self.name} 年龄: {self.age}'
    
    a = A('赵海狗',35)
    b = A('李业',56)
    c = A('华丽',18)
    print(a)
    print(repr(a))
    """
    666
    姓名:赵海狗 年龄:35
    666
    姓名:赵海狗 年龄: 35
    """
    
    # 用法同 __str__
    

    __call__ ***

    # 对象() 自动触发对象从属于类(父类)的__call__方法
    class Foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    obj = Foo()
    obj()
    """
    __call__
    """
    

    __eq__

    class A(object):
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __eq__(self,obj):
            if  self.a == obj.a and self.b == obj.b:
                return True
            
    x = A()
    y = A()
    print(x == y)
    """
    True
    """
    

    __del__

    # 析构方法,当对象在内存中被释放时,自动触发执行。
    
    # 注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
    class A:
    
        def __del__(self):
            print(666)
    
    obj = A()
    del obj
    """
    666
    """
    

    __new__

    class A(object):
        def __init__(self):
            self.x = 1
            print("in init function")
        def __new__(cls, *args, **kwargs):
            print("in new function")
            return object.__new__(A)
    a = A()
    
    """
    in new function
    in init function
    """
    
    # 对象是object类的__new__方法 产生一个对象
    # 类名()
    # 1.先触发 object 的__new__方法, 此方法在内存中开辟一个对象空间.
    # 2.执行__init__方法,给对象封装属性
    
    

    单例模式

    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)
    obj1 = A("李业")
    obj2 = A("wusir")
    print(obj1.name)
    print(obj.name)
    print(obj2.name)
    """
    <__main__.A object at 0x000001E4CFC676A0>
    wusir
    wusir
    wusir
    """
    

    __item__

    # __getitem__ __setitem__ __delitem__ 对对象做类似于字典的 (增删改查) 触发__item__系列
    # __delattr__ del obj.属性 就会触发此方法 
    
    class Foo:
        def __init__(self, name):
            self.name = name
    
        def __getitem__(self, item):
            print(item)
            print(666)
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            self.__dict__[key] = value
            print(key)
            print(value)
    
        def __delitem__(self, key):
            print("del obj[key]时, 我执行")
    
        def __delattr__(self, item):
            print(f"对象的{item}属性已经删除")
    
    
    f1 = Foo("sb")
    print(f1["name"])
    f1[1] = 2
    del f1[1]
    del f1.name
    """
    name
    666
    sb
    1
    2
    del obj[key]时, 我执行
    对象的{name}属性已经删除
    """
    

    __enter__ __exit__

    class A:
        def __init__(self, name):
            self.name = name
        
        def __enter__(self):
            print(666)
        
        def __exit__(self, exc_type, exc_val, exc_tb):
            print(777)
    # 第一种实例化方式
    obj = A("海狗")
    # 第二种实例化方式, 必须基于__enter__ 和 __exit__这两个方法
    with A("海狗") as obj:
        print(obj.name)
    
    class A:
        def __init__(self, text):
            self.text = text
    
        def __enter__(self):    # 开启上下文管理器对象时触发此方法
            self.text = self.text + '您来了'  # 第一步
            print(11111)
            return self     # 必须!!!将实例化的对象返回f1
    
        def __exit__(self, exc_type, exc_val, exc_tb):    # 执行完上下文管理器对象f1时触发此方法
            print(333)    # 第三步
            self.text = self.text + ',这就走了'
    
    with A('大爷') as f1:
        print(2222)
        print(f1.text)   # 第二步
    print(f1.text)   # 第四步
    """
    11111
    2222
    大爷您来了
    333
    大爷您来了,这就走了
    """
    

    __iter__

    class A:
        def __init__(self, name):
            self.name = name
        def __iter__(self):
            for i in range(10):
                yield i
        # def __next__(self):
        #     pass
    obj = A("李业")
    print('__iter__' in dir(obj))
    print(hasattr(obj, "__iter__"))
    # 以上两行都在判断对象是否具有__iter__
    for i in obj:
        print(i)
    
  • 相关阅读:
    pikachu-xss(1)
    eNSP上配置RIPv2的认证
    eNSP模拟器OSPF单区域配置
    OSPF与ACL综合实验
    利用单臂路由实现vlan间路由
    理解Hybrid接口的应用
    eNSP下配置Trunk接口实现跨交换机传递数据
    eNSP上VLAN的基础的配置及access接口
    eNSP下利用三层交换机实现VLAN间路由
    NFS网络文件系统
  • 原文地址:https://www.cnblogs.com/beichen123/p/11342253.html
Copyright © 2011-2022 走看看