类属性设置方法

  • 1. 类实例容器操作容器值
    • 1.1 __gititem__魔术
    • 1.2 __setitem__魔术
    • 1.3 实际案例
  • 2. 实例属性增删改
    • 2.1 __getattr__魔术
      • 2.1.1 案例说明
    • 2.2 __setattr__魔术
      • 2.2.1 案例函数体为打印语句
      • 2.2.2 案例函数体为实例字典添加属性语句
    • 2.3 __delattr__删除属性魔术
  • 3.对象属性增删改
    • 3.1 getattr()
    • 3.2 setattr()
  • 4. 字典属性化访问
    • 4.1 字典实例化


1. 类实例容器操作容器值

1.1 __gititem__魔术

实现self[key]访问,序列对象,key接受整数为索引,或者切片,对于set和dict,key为hashable。key存在时引发异常。为避免key不存在引发异常,可以通过__missing__魔术解决

1.2 __setitem__魔术

实现self[key]=value对象添加,

1.3 实际案例

根据如上两种魔术方法,可知此实例的魔术方法都是操作实例容器的,具体代码如下:

dicta = {"a":1,"b":2,"c":3}
class B:
    def __init__(self,dictobj):
        self.d = dictobj

    def __getitem__(self, item):
        return self.d.get(item)

    def __setitem__(self, key, value):
        self.d[key]=value

b = B(dicta)
#通过索引访问实例容器时,就会调用类属性__getitem__魔术
print(b["a"])

#通过索引访问设置实例容器的值
b["d"] = 4
print(b.d)

#######################
#运行结果
1
{'d': 4, 'b': 2, 'c': 3, 'a': 1}

2. 实例属性增删改

如下魔法主要是对实例属性的操作,和对实例容器操作的概念完全不同

2.1 __getattr__魔术

一个类的属性会按照继承关系找,如果找不到,就会执行__getattr__()方法,如果没有这个方法,就会抛出AttributeError异常表示找不到属性。
查找属性顺序为:
instance.__dict__ --> instance.__class__.__dict__ -->继承的祖先类(直到object)的__dict__-->找不到-->调用__getattr__()

2.1.1 案例说明

class Base:
    n = 0

class Point(Base):
    """doc"""
    z = 6

    def __init__(self,x,y):
        self.x = x
        self.y = y

    def show(self):
        print(self.x,self.y)

    def __getattr__(self, item):
        return "missing {}".format(item)

p1 = Point(4,5)
print(p1.x)
print(p1.z)
print(p1.n)
print(p1.t)
########################
#运行结果如下:
4
6
0
missing t

2.2 __setattr__魔术

只要是给实例添加属性就要调用__setattr__魔术,如在初始化时self.x=x时,或者其他方法中slef.x = x,通常都会调用此魔术,正常情况下__setattr__函数内容如下:

class A:
    def __setattr__(self,key,vaule):
        self.__dict__[key] = value

如果遇到__setattr__的函数内容为其他语句时,当个self.x=x 属性增加属性时,就会按照此函数给添加内容

2.2.1 案例函数体为打印语句

__setattr__函数体中仅仅为打印语句,预计无法将属性添加至实例字典中

class Base:
    n = 0
class Point(Base):
    """doc"""

    def __init__(self,x,y):
        self.x = x
        self.y = y

    def show(self):
        print(self.x,self.y)

    def __getattr__(self, item):
        print(4,item,"``````````````")
        print(5,type(item))

    def __setattr__(self, key, value):
        #预计实例属性字典为空
        print(10,key,type(key))
        print(11,value,type(value))

p1 = Point(4,5)
print(1,p1.x,p1.y)
print(2,p1.n)
print(3,p1.__dict__)
##############################
#运行结果如下:属性字典为空
10 x <class 'str'>
11 4 <class 'int'>
10 y <class 'str'>
11 5 <class 'int'>
4 x ``````````````
5 <class 'str'>
4 y ``````````````
5 <class 'str'>
1 None None
2 0
#如下实例字典为空
3 {}

2.2.2 案例函数体为实例字典添加属性语句

__setattr__魔术中有给实例字典添加属性,预计正常给实例添加属性

class Base:
    n = 0

class Point(Base):
    """doc"""

    def __init__(self,x,y):
        self.x = x
        self.y = y

    def show(self):
        print(self.x,self.y)

    def __getattr__(self, item):
        print(4,item,"``````````````")
        print(5,type(item))

    def __setattr__(self, key, value):
        print(10,key,type(key))
        print(11,value,type(value))
        self.__dict__[key] = value

p1 = Point(4,5)
print(1,p1.x,p1.y)
print(2,p1.n)
print(3,p1.__dict__)
#########################################
#运行结果如下:预计正常添加实例属性
10 x <class 'str'>
11 4 <class 'int'>
10 y <class 'str'>
11 5 <class 'int'>
1 4 5
2 0
#如下实例字典正常
3 {'x': 4, 'y': 5}

2.3 __delattr__删除属性魔术

在删除实例的属性时会调用此方法

3.对象属性增删改

若对一个类对象的属性进行增加或删除时,通常采用内建函数

3.1 getattr()

内建函数getattr(object, name, default=None),通常在一个对象上获取某一属性,如下:

class Point(Base):
    """doc"""

    def __init__(self,x,y):
        self.x = x
        self.y = y

    def show(self):
        print("test")

p1 = Point(4,5)
getattr(p1,"show")()
###############################
#运行如下:
test

3.2 setattr()

给实例对象或者类对象增加某属性,若对实例增加属性时,任然调用的是__setattr魔术,如下:

class Point(Base):
    """doc"""

    def __init__(self,x,y):
        self.x = x
        self.y = y

    def __getattr__(self, item):
        print(4,item,"``````````````")
        print(5,type(item))

    def __setattr__(self, key, value):
        print(10,key,type(key))
        print(11,value,type(value))
        # self.__dict__[key] = value

p1 = Point(4,5)
setattr(p1,"a",123)
print(p1.__dict__)
################################
#运行结果如下:
10 x <class 'str'>
11 4 <class 'int'>
10 y <class 'str'>
11 5 <class 'int'>
10 a <class 'str'>
11 123 <class 'int'>
{}

4. 字典属性化访问

4.1 字典实例化

如何访问一个字典的一个值就像访问一个类属性一样?,而且禁止修改属性

d = {"a":1,"b":2,"c":3}
class AttrDict:
    def __init__(self,d:dict):
        self.__dict__.update(d if isinstance(d,dict) else {})

    def __setattr__(self, key, value):
        raise NotImplementedError

    def __repr__(self):
        return "".format(self.__dict__)

ad = AttrDict(d)
print(ad.__dict__)
print(ad.a)
print(ad.b)
print(ad.c)

你可能感兴趣的:(python)