python类特列方法使用

class Rgc(object):
    def __new__(cls, *args, **kwargs):
        print('在类通过__new__方法实例化一个对象')
        return super(Rgc, cls).__new__(cls)

    def __init__(self, name, gender):
        """
        Usage:
        >>> Rgc('rg','man')
        :param name:
        :param gender:
        """
        print('在类通过__new__方法实例化为一个对象后,此方法是对这个对象 参数的初始化(先执行__new__,再执行__init)')
        self.name = name
        self.gender = gender

    def __call__(self, age):
        """
        把类实例化对象当做一个方法调用;

        Usage:
            >>> rg_obj=Rgc('rg','man')
            >>> rg_obj(14)
            >>> 14

            >>> Rgc('rg','man')(14)
            >>> 14

        :param age:
        :return:
        """
        print("""把类实例化对象当做一个方法调用;""")
        return age

    def __str__(self):
        return '用户输出的数据,通过print方法显示的内容'

    def __repr__(self):
        return "控制台输出的内容,只有在控制台时才会显示"

    def __enter__(self):
        """
        __enter__方法配合__exit__方法使用,主要用来 以 with xxxx as xxx: 的方式(比如访问文件)调用
        __enter__ 必须有 return ,并且return 的结果作为as后面的变量使用。

        Usage:
            >>> with Rgc('rg','girl') as rg_obj:
            >>>     print(rg_obj.name)

        :return: obj
        """
        print('进入with')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        __exit__函数 是 在 with xxxx as xxx: 的语句结束时需要处理的相关数据,如释放链接,清除内存等
        :param exc_type:
        :param exc_val:
        :param exc_tb:
        :return:
        """

        print('退出with')


class St():
    mana_list = []
    mana_dict = {}

    def __init__(self, num):
        self.names = num
        self.mana_list.append(num)
        self.mana_dict[num] = self

    def __getitem__(self, item):
        """
        此方法可以把对象模拟成list或dict 的方式调用,即 key-val 类型
        但是此方法 需要用到 类属性,类多次实例化时,类属性的值共享,所以 需要注意 使用情况
        使用事例 如下方 代码
        :param item:
        :return:
        """
        if isinstance(item, str):
            return self.mana_dict[item]
        else:
            return self.mana_list[item]


fir = St('first')
sec = St('secound')
thi = St('third')
print(thi.mana_list, '分割',
      thi.mana_dict)  # ['first', 'secound', 'third'],'分割', {'first': <__main__.St object at 0x000001C6DF19AA58>, 'secound': <__main__.St object at 0x000001C6DF19AA90>, 'third': <__main__.St object at 0x000001C6DF19AAC8>}

print(thi[1], thi['third'].names)  # secound third

print(fir.__dict__)  # {'names': 'first'}    总结:实例化对象的__dict__存了实例化属性,即 self.xxx=yyy
print(St.__dict__)
# {'__module__': '__main__', 'mana_list': ['first', 'secound', 'third'], 'mana_dict': {'first': <__main__.St object at 0x00000231144BAA90>, 'secound': <__main__.St object at 0x00000231144BAAC8>, 'third': <__main__.St object at 0x00000231144BAB00>}, '__init__': <function St.__init__ at 0x00000231144CF1E0>, '__getitem__': <function St.__getitem__ at 0x00000231144CF268>, '__dict__': <attribute '__dict__' of 'St' objects>, '__weakref__': <attribute '__weakref__' of 'St' objects>, '__doc__': None}
# 总结:类的__dict__存了全局变量,静态函数,类函数,普通函数,内置属性

print(fir.__dir__())
# ['names', '__module__', 'mana_list', 'mana_dict', '__init__', '__getitem__', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
# 总结:实例化的 __dir__() 存了 全局变量,静态函数,类函数,普通函数,内置属性 的名字 列表

print(thi.__class__.mana_list)  # 获取实例化 属性值
print(thi.__class__.__name__)  # 获取 实例化 类 的 名字 字符串 值

print('*' * 20)


class AttTest():
    nu = 1
    a = 4

    def __init__(self, nu):
        self.nu = nu

    def __getattr__(self, item):
        """
        属性查找顺序为:
        实例的__getattribute__-->实例对象字典-->实例所在类字典-->实例所在类的父类(MRO顺序)字典-->实例所在类的__getattr__-->报错
        :param item:
        :return:
        """
        print('在访问未定义的属性时,调用此方法,如果不显示的引用此方法 则程序直接报错;此方法在属性访问顺序的末端')
        return '不存在此属性'


te = AttTest(20)
print(te.nu, AttTest.nu)
print(getattr(te, 'nu'), 'getattr 实例化')  # getattr() 方法访问实例的属性  结果为 20
print(getattr(AttTest, 'nu'), 'getattr obj')  # getattr() 方法访问类属性 结果为 1
print(te.a1)

print('*' * 20)


class AttTestOne:
    nu = 1
    a = 4

    def __init__(self, nu):
        self.nu = nu

    def __getattribute__(self, item):
        """
        此方法 叫 属性访问拦截器,此拦截器是 属性访问顺序中 优先级最高的,会先执行此方法的代码;
        属性查找顺序为:
        实例的__getattribute__-->实例对象字典-->实例所在类字典-->实例所在类的父类(MRO顺序)字典-->实例所在类的__getattr__-->报错

        waring: 注意此方法 如果 return self.item 会造成 死循环
        :param item:
        :return:
        """
        print('start getattribute func')
        if item == 'nu':
            return True
        return False


te_one = AttTestOne(22)
print(te_one.nu)

print('*' * 20)


class SetattTest(object):
    private = ['age']

    def __init__(self, job):
        self.job = job

    def __setattr__(self, key, value):
        """
        此__setattr__ 在对实例 赋值,或者在__init__中初始化参数时,调用此方法,注意 此方法里面 不要使用 self.key=value ,因为会无限 调用 __setattr__方法 导致报错。
        此方法 在设置属性时使用 self.__dict__[key] = value
        其他功能 比如 可以强制设置类的private方法

        :param key:
        :param value:
        :return:
        """
        print('start {},{}'.format(key, value))
        # self.key=value
        if key in self.private:
            raise AttributeError('this attribute can not be changed!')
        else:
            self.__dict__[key] = value
            # self.key=value # 对属性赋值不要用此方法,会无限循环最终报错


aa = SetattTest('work')
aa.name = 'a'
# aa.age = 'b'
print(aa.__dict__)

__all__ = ['SetattTest', 'AttTestOne']
"""
__all__方法 里面是 函数或 常量 或 类 的名字,一般在 __init__.py 文件中使用,在其他地方 通过 from df import * 时,只会导入 __all__里的方法
"""

 

posted @ 2019-03-05 18:30  RGC  阅读(436)  评论(0编辑  收藏  举报