zoukankan      html  css  js  c++  java
  • 面向对象之:元类,反射, 双下方法

    1.元类

    class A:
        pass
    obj = A()
    
    print(type('abc'))		# <class 'str'>
    print(type([1,2,3]))	# <class 'list'>
    print(type((22,33)))	# <class 'tuple'>
    
    # type 获取对象从属于的类
    print(type(A))		# <class 'type'>
    print(type(str))	# <class 'type'>
    print(type(dict))	# <class 'type'>
    

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

    # type 与 object 的关系.
    # print(type(object)) object类是type类的一个实例.
    # object类是type类的父类.
    
    print(issubclass(type,object))
    

    2.反射

    实例对象 类 本模块 其他模块

    hasattr getattr setattr delattr

    2.1实例对象:

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

    2.2从类的角度:

    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)
    

    2.3从其他模块:

    import tbjx
    print(getattr(tbjx,'name'))
    getattr(tbjx,'func')()
    
    # 1. 找到tbjx对象 的C类,实例化一个对象.
    print(getattr(tbjx,'C'))
    obj = getattr(tbjx,'C')('123')
    # 2. 找到tbjx对象 的C类,通过对C类这个对象使用反射取到area.
    print(getattr(tbjx.C,'area'))
    # 3. 找到tbjx对象 的C类,实例化一个对象,对对象进行反射取值.
    obj = getattr(tbjx,'C')('赵海狗')
    print(obj.name)
    print(getattr(obj,'name'))
    # 从当前模块研究反射:
    a = 666
    
    def func1():
        print('in 本模块这个对象')
    
    def func1():
        print('in func1')
    
    def func2():
        print('in func2')
    
    def func3():
        print('in func3')
    
    def func4():
        print('in func4')
    
    import sys
    # print(sys.modules[__name__])
    # print(getattr(sys.modules[__name__],'a'))
    # getattr(sys.modules[__name__],'func1')()
    # getattr(sys.modules[__name__],'func2')()
    # getattr(sys.modules[__name__],'func3')()
    
    func_lst = [f'func{i}' for i in range(1,5)]
    print(func_lst)
    for func in func_lst:
        getattr(sys.modules[__name__],func)()
    
    class User:
    
        user_list = [('login','登录'),('register','注册'),('save', '存储')]
    
        def login(self):
            print('欢迎来到登录页面')
    
        def register(self):
            print('欢迎来到注册页面')
    
        def save(self):
            print('欢迎来到存储页面')
    
    
    while 1:
        choose = input('请输入序号: 
    1: 登录
    2: 注册
    3: 存储
    ').strip()  # 1
        obj = User()
        getattr(obj, obj.user_list[int(choose)-1][0])()  # getattr(obj,'login')
    
    

    3.函数与方法的区别

    def func1():
        pass
    
    class A:
        def func(self):
            pass
    
    # 1. 通过打印函数名的方式区别什么是方法,什么是函数. (了解)
    print(func1)
    print(A.func)  # 通过类名调用的类中的实例方法叫做函数.
    obj = A()
    print(obj.func) # 通过对象调用的类中的实例方法叫方法.
    
    # 2. 可以借助模块判断是方法还是函数.
    
    from types import FunctionType
    from types import MethodType
    
    def func():
        pass
    
    class A:
        def func(self):
            pass
    
    obj = A()
    
    
    print(isinstance(func,FunctionType))  # True
    print(isinstance(A.func,FunctionType))  # True
    print(isinstance(obj.func,FunctionType))  # False
    print(isinstance(obj.func,MethodType))  # True
    
    # 总结:
    # python 中一切皆对象, 类在某种意义上也是一个对象,python中自己定义的类,
    # 以及大部分内置类,都是由type元类(构建类)实例化得来的.
    # python 中一切皆对象, 函数在某种意义上也是一个对象,函数这个对象是从FunctionType这个类实例化出来的.
    # python 中一切皆对象, 方法在某种意义上也是一个对象,方法这个对象是从MethodType这个类实例化出来的.
    
    class A:
        @classmethod
        def func(cls,a):
            pass
    
        @staticmethod
        def func1():
            pass
    
    # A.func(222)
    # A.func()
    # obj = A()
    # obj.func()
    
    # 总结: 如何判断类中的是方法还是函数.
    # 函数都是显性传参,方法都是隐性传参.
    

    4.特殊双下方法

    特殊的双下方法: 原本是开发python这个语言的程序员用的.源码中使用的.
    str : 我们不能轻易使用.慎用.
    双下方法: 你不知道你干了什么就触发某个双下方法.

    4.1__len__

    class B:
    
        def __init__(self,name,age):
            self.name = name
            self.age =age
    
        def __len__(self):
            print(self.__dict__)
    
            return len(self.__dict__)  # 2
    
    b = B('leye',28)
    
    print(len(b))
    # dict
    print(len({'name': 'leye', 'age': 28}))
    

    4.2__len__

    class A(object):
    
        pass
    
    obj = A()
    
    print(hash(obj))
    print(hash('fdsaf'))
    

    4.3__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)
    # 打印对象触发__str__方法
    print(f'{a.name}  {a.age}')
    print(f'{b.name}  {b.age}')
    print(f'{c.name}  {c.age}')
    print(a)
    print(b)
    print(c)
    # 直接str转化也可以触发.
    print(str(a))
    

    4.4__repr__

    print('我叫%s' % ('alex'))
    print('我叫%r' % ('alex'))
    print(repr('fdsaf'))
    
    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))
    

    4.5__call__

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

    4.6__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
            return True
    x = A()
    y = A()
    print(x == y)
    x = 1
    y = 2
    print(x+y)
    

    4.7__del__

    __del__析构方法
    
    class A:
    
        def __del__(self):
            print(666)
    
    obj = A()
    del obj
    

    4.8__new__

    # __new__ *** 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)  # object 342534
    
    # 对象是object类的__new__方法 产生了一个对象.
    a = A()
    
    # 类名()
    # 1. 先触发 object的__new__方法,此方法在内存中开辟一个对象空间.
    # 2. 执行__init__方法,给对象封装属性.
    
    print(a)
    
    # python中的设计模式: 单例模式
    
    # 一个类只允许实例化一个对象.
    class A:
        pass
    
    obj = A()
    print(obj)
    obj1 = A()
    print(obj1)
    obj2 = A()
    print(obj2)
    
    # 手写单例模式
    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('李业')
    print(obj1.name)
    print(obj.name)
    

    4.9__item__

    getitem setitem delitem 对对象做类似于字典(增删改查)触发__item__系类

    delattr del obj.属性 就会出发此方法

    class Foo:
        def __init__(self,name):
            self.name = name
    
        def __getitem__(self,key):
            print(key)
            print(666)
            return self.__dict__[key]
    
        def __setitem__(self,key,val):
            self.__dict__[key] = val
            print(key)
            print(val)
    
        def __delitem__(self,key):
            self.__dict__.pop(key)
            print('delitem')
    
    
        def delattr(self,key):
            print('执行delattr函数')
            # super().__delattr__(key)    # 调用父类的方法 会直接删除
    
    p = Foo('la')
    print(p['name'])
    p[1] = 2
    # p['age']        # 没有此属性 报错
    del p[1]
    
    del p['name']
    print(p.name)   # 报错
    
    p['age'] = 18
    p['la'] = 19
    del p.age
    del p['la']
    

    4.10__enter__ __exit__

    class A:
    
        def __init__(self, text):
            self.text = text
            print('__init__')  # 第一步
    
        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 p:
        print(2222)
        print(p.text)  # 第三步
    print(p.text)  # 第五步
    

    4.11__iter__

    class A:
    
        def __init__(self,name):
            self.name = name
    
        def __iter__(self):
            for i in range(10):
                yield i
    object
        # def __next__(self):
        #     pass
    obj = A('李业')  # obj 一个可迭代对象
    # print('__iter__' in dir(obj))
    # for i in obj:
    #     print(i)
    
    # print(obj.name)
    o = iter(obj)
    print(next(o))
    print(next(o))
    print(next(o))
    print(next(o))
    print(next(o))
    print(next(o))
    
  • 相关阅读:
    关于使用css3属性:transform固定菜单位置,在滑动页面时菜单闪现抖动的问题
    使用iscroll.js插件时,遇到在Android端无法点击a超链的解决办法
    window.external的使用
    SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
    chain.doFilter(request,response)含义
    巧用Ajax的beforeSend 提高用户体验
    getRequestDispatcher(path).forward(),,执行完,后面的代码居然还会执行!!!记得加return 啊亲
    @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
    ajax修改表单的值后dom没更新的解决办法
    .net core json序列化首字符小写和日期格式处理
  • 原文地址:https://www.cnblogs.com/fengqiang626/p/11331292.html
Copyright © 2011-2022 走看看