zoukankan      html  css  js  c++  java
  • python面向对象之数据和自省(私有属性、内置属性、自定义属性和描述器)

    一、私有属性

    • 类里面定义的变量叫类属性,类属性有两种:公有属性和私有属性
    • 私有属性定义:

            单下划线开头:_attr

            双下划线开头:__attr

    python中并未实现属性的真正私有化,但可以用下划线实现伪私有。

    class MyClass():
        attr1="attr1"
        _attr2="attr2"
        __attr3="attr3"
    
    m=MyClass()
    #访问公有属性
    print(MyClass.attr1)
    print(m.attr1)
    
    #访问单下划线私有属性
    print(MyClass._attr2)
    print(m._attr2)
    
    #访问双划线私有属性
    print(MyClass._MyClass__attr3)  #访问私有属性需要在属性名称前面加上"_类名"
    print(m._MyClass__attr3)
    
    print(MyClass.__dict__)   #查看该类的所有属性和方法

    运行结果:

    attr1
    attr1
    attr2
    attr2
    attr3
    attr3
    {'__module__': '__main__', 'attr1': 'attr1', '_attr2': 'attr2', '_MyClass__attr3': 'attr3', '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None}

    二、__dict__

    类调用__dict__属性,返回类的属性和方法的字典。

    实例调用__dict__属性,返回实例相关的属性和方法。

    class MyClass():
        attr1="attr1"
    
        def __init__(self,name):
            self.name=name
    
        def test(self):
            print("这是一个test方法")
    
    m=MyClass("crystal")
    print(m.__dict__)  #运行结果: {'name': 'crystal'}
    print(MyClass.__dict__)    #运行结果:{'__module__': '__main__', 'attr1': 'attr1', '__init__': <function MyClass.__init__ at 0x10f8460d0>, 'test': <function MyClass.test at 0x10f846158>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None}

    三、内置属性__slots__

    默认情况下,类的实例有一个字典用于存储属性,这对于具有很少实例变量的对象会浪费空间。当创建大量实例时,空间消耗会很大。

    可以通过在类定义中定义__slots__来覆盖默认__dict__行为。

    class Base(object):
        #指定类对象所能绑定的属性
        #限制属性
        #节约内存,定义了__slots__属性后,那么该对象不会再自动生成__dict__属性
        __slots__ = ['name']
        pass
    
    b=Base()
    # b.age="20"   #  'Base' object has no attribute 'age'
    b.name="crystal"
    
    # print(b.__dict__)   #'Base' object has no attribute '__dict__'

    四、自定义属性访问

    可以定义下面的方法来访问、赋值或删除自定义类实例。

    • object.__getattr__:当查找不到属性,触发AttributeError异常时会调用此方法
    • object.__getattribute__:查找属性时,第一时间会调用此方法
    • object.__setattr__:设置属性时,调用此方法给属性赋值
    • object.__delattr__:删除属性时触发此方法

    (1)获取属性方法

    class Test:
    
        def __getattr__(self, item):
            print("这是__getattr__方法")
            return 100
    
        def __getattribute__(self, item):
            print("这是__getattribute__方法")
            return super().__getattribute__(item)
    
    t=Test()
    
    t.name=999
    print(t.name)
    print("-------------------")
    print(t.name1)

    运行结果:

    这是__getattribute__方法
    999
    -------------------
    这是__getattribute__方法
    这是__getattr__方法
    100

    (2)设置属性方法

    class Test:
    
        def __setattr__(self, key, value):
            #此方法在给对象设置属性时会触发
            print("这是__setattr__方法")
            if key=="age":
                super().__setattr__(key, 18)
            else:
                super().__setattr__(key,value)
    
    t=Test()
    
    t.name=999
    print(t.name)
    print("-------------------")
    t.age=200
    print(t.age)

    运行结果:

    这是__setattr__方法
    999
    -------------------
    这是__setattr__方法
    18

    (3)删除对象属性方法

    class Test:
    
        def __delattr__(self, item):
            print("这是__delattr__方法")
            super().__delattr__(item)
    t=Test()
    
    t.name=999
    print(t.name)
    print("--------------")
    del t.name
    print(t.name)

    运行结果:

    999
    --------------
    这是__delattr__方法
    Traceback (most recent call last):
      File "/Users/grace/PycharmProjects/selenium/test.py", line 375, in <module>
        print(t.name)
    AttributeError: 'Test' object has no attribute 'name'

    五、描述器

    描述器是一个具有绑定行为的对象属性,如果一个对象定义以下方法中的任何一个,它被称为描述器。

    object.__get__(self,instance,owner):获取属主类的属性或者该类的一个实例的属性。

    object.__set__(self,instance,value):设置属主类实例的属性的值

    object.__delete(self,instance,value):删除属主类实例的属性。

    实例:

    class Field:
    
        def __get__(self, instance, owner):
            print("__get__方法被触发")
            print("owner:", owner)  #属主类:<class '__main__.Model'>
            return self.value
    
        def __set__(self, instance, value):
            print("__set__方法被触发")
            print("self:", self)  #描述器的实例:<__main__.Field object at 0x1128d3048>
            print("instance:", instance) #属主类的实例: <__main__.Model object at 0x1128d3080>
            print("value:", value)
            self.value=value
    
        def __delete__(self, instance):
            print("__delete__方法被触发")
            del self.value
    
    class Model(object):
        name="musen"
        attr=Field()
    
    m=Model()
    m.attr=10
    print("-----------")
    print(m.attr)
    print("-------------")
    del m.attr

    运行结果:

    __set__方法被触发
    self: <__main__.Field object at 0x10679e080>
    instance: <__main__.Model object at 0x10679e0f0>
    value: 10
    -----------
    __get__方法被触发
    owner: <class '__main__.Model'>
    10
    -------------
    __delete__方法被触发

    使用描述器实现ORM模型中的字段类型: 参考https://www.cnblogs.com/crystal1126/p/13625306.html

  • 相关阅读:
    OSPF
    【今日CS 视觉论文速览】 24 Jan 2019
    【今日CS 视觉论文速览】Wed, 23 Jan 2019
    【今日CS 视觉论文速览】 21 Jan 2019
    【Processing学习笔记】安装与入门
    【今日CS 视觉论文速览】Part2, 18 Jan 2019
    【今日CS 视觉论文速览】Fri, 18 Jan 2019
    【今日CS 视觉论文速览】Thu, 17 Jan 2019
    【今日CS 视觉论文速览】Part2, 16 Jan 2019
    【今日CS 视觉论文速览】Wed, 16 Jan 2019
  • 原文地址:https://www.cnblogs.com/crystal1126/p/13576875.html
Copyright © 2011-2022 走看看