python高阶编程(十):属性

1、私有属性

Python并没有真正的私有化支持,但可用下划线得到伪私有,有一项大多数 Python 代码都遵循
的习惯:带有下划线,前缀的名称应被视为非公开的 API 的一部分(无论是函数、 方法还是数据
成员)。它应被视为实现细节
1、私有的属性和方法为双下滑先开头的
2、在类里面不管是私有的属性,还是方法,都只能在类里面使用
3、私有的属性和方法是不能继承

2、 dict

类调用 dict 属性,返回类属性和所有方法的字典。
实列调用 dict 属性,返回的值实列相关的实例属性

class Demo3:
    attr = 100
    # 类的私有属性
    _attr = 900  # 声明式的私有属性(程序员之间默认的私有属性)
    __attr2 = 200  # 真正的私有属性

    def __init__(self):
        # 对象的私有属性
        self.__name = 'demo3'
        self.name = 'demo3333'

    @classmethod
    def work(cls):
        # 获取私有的类属性
        print(cls.__attr2)
        # 调用私有的类方法
        cls.__work2()
        print('----work----')

    # 类私有的方法
    @classmethod
    def __work2(cls):
        print("---work2------")

    def work4(self):
        # 在类里面获取私有实例属性
        print(self.__name)
        # 调用私有的实例方法
        self.__work5()
        print('----work4-----')

    # 对象的私有方法(私有的实例方法)
    def __work5(self):
        print('-------work5-----')


print(Demo3.__dict__)
d = Demo3()
print(d.__dict__)
# 结果
{'__module__': '__main__', 'attr': 100, '_attr': 900, '_Demo3__attr2': 200, '__init__': <function Demo3.__init__ at 0x0000023BA8D03400>, 'work': <classmethod object at 0x0000023BA8D1A978>, '_Demo3__work2': <classmethod object at 0x0000023BA8D1A9E8>, 'work4': <function Demo3.work4 at 0x0000023BA8D03598>, '_Demo3__work5': <function Demo3.__work5 at 0x0000023BA8D03620>, '__dict__': <attribute '__dict__' of 'Demo3' objects>, '__weakref__': <attribute '__weakref__' of 'Demo3' objects>, '__doc__': None}
{'_Demo3__name': 'demo3', 'name': 'demo3333'}

3、内置属性 slots

默认情况下,类的实例有一个字典用于存储属性。这对于具有很少实例变量的对象会浪费空间。当创建
大量实例时,空间消耗可能会变得尖锐。
可以通过在类定义中定义 __ slots __ 来覆盖默认 __dict__ 行为。 __ slots __ 声明接受一个实例变量序
列,并在每个实例中只保留足够保存每个变量值的空间。因为没有为每个实例创建 __ dict __ ,所以
节省空间。
定义过slots属性来限制类实例的属性,只能绑定slots指定的属性。不能添加slots之外的属性
__slots__ 的两个作用:
1、限制实例对象的属性
2、阻止属性字典的创建(对象不会拥有__dict__)

class Demo:
    # 通过__slots__属性可以限制类的实例 的属性
    #
    # __slots__ = ['name', 'age']
    __slots__ = []

    def work(self):
        print("---work----")


d = Demo()

d.work()
# d.name = 99
d.age = 999

#结果
Traceback (most recent call last):
---work----
  File "D:/LTT/XXX.py", line 48, in <module>
    d.age = 999
AttributeError: 'Demo' object has no attribute 'age'

4、自定义属性访问

可以定义下面的方法来自定义类实例的属性访问的含义(访问、赋值或者删除 x.name )。

# 当属性查找在通常的地方没有找到该属性时调用
object.__getattr__
# 查找属性时,第一时间会调用该方法
object.__getattribute__
# 设置属性时,调用该方法设置属性,
object.__setattr__
# 在del obj.attr删除属性时触发
object.__delattr__
class Demo(object):

    def __init__(self, name, age):
        """
        :param name: str类型
        :param age: int类型
        """
        print("____init_____方法开始")
        self.name = name
        self.age = age
        print("____init_____方法结束")

    def __setattr__(self, key, value):
        """在__setattr__方法中可以对属性的创建过程做干预"""
        # 属性设置的魔术方法
        print("____setattr_____方法开始")
        if key == 'name':
            if isinstance(value, str):
                # 调用父类的__setattr__方法设置属性
                super().__setattr__(key, value)
            else:
                raise TypeError('name属性的值必须为字符串')
        elif key == 'age':
            if isinstance(value, int):
                # 调用父类的__setattr__方法设置属性
                super().__setattr__(key, value)
            else:
                raise TypeError('age属性的值必须为int类型')
        else:
            super().__setattr__(key, value)
        # print("属性{},值为{}".format(key, value))

    def __delattr__(self, item):
        """删除属性的方法"""
        if item == 'name':
            raise AttributeError('name属性不支持删除')
        else:
            # 调用父类的属性进行删除操作
            super().__delattr__(item)

    def __getattribute__(self, item):
        """获取属性的方法"""
        print("获取的属性名为:", item)
        # 调用父类的方法去获取属性
        try:
            value = super().__getattribute__(item)
        except AttributeError:
            value = None
        return value
    # 同时定义__getattribute__和__getattr__时,__getattr__方法不会再被调用
    def __getattr__(self, item):
        """获取的属性不存在时,触发的方法"""
        print('__getattr__方法', item)
        pass


dd = Demo('musen', 999)
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束

dd.sex = '男'
print(dd.__dict__)
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
____setattr_____方法开始
获取的属性名为: __dict__
{'name': 'musen', 'age': 999, 'sex': '男'}

del dd.age
delattr(dd, 'sex')
print(dd.__dict__)
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
____setattr_____方法开始
__delattr__方法 age
__delattr__方法 sex
获取的属性名为: __dict__
{'name': 'musen'}

print(dd.age1)
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
获取的属性名为: age1
None
# 类中没有定义__getattribute__
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
__getattr__方法 age1
None

hasattr(dd, 'age')
#结果
____init_____方法开始
____setattr_____方法开始
____setattr_____方法开始
____init_____方法结束
获取的属性名为: age
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值