python类属性,类方法的学习

一、__getattr__和__getattribute__的区别

getattr(self, item)定义当用户试图获取一个不存在的属性的行为 
getattribute(self, item)定义该类的属性被访问时的行为

因为,计算机肯定先访问存在的属性,如果没有,再访问不存在的属性,即先访问getattribute(self, item),再访问getattr(self, item)

1、demo01

class Demo:
    def __getattr__(self, item):
        return "该属性不存在"

demo=Demo()
print (demo.x)
## 该属性不存在

2、demo0

class C:
    def __getattr__(self, name):
        print(1)

    def __getattribute__(self, name):
        print(2)

    def __setattr__(self, name, value):
        print(3)

    def __delattr__(self, name):
        print(4)

c = C()
c.x = 1
# 位置一,请问这里会显示什么?
print(c.x)
# 位置二,请问这里会显示什么?

位置一会显示3,因为c.x=1是赋值操作,所以会访问setattr()魔法方法:位置二显示2和None,因为x是属于实例对象c的属性,所以c.x是访问一个存在的属性,因为会访问getattribute()魔法方法,但我们重写了这个方法,使得它不能按正常的逻辑返回属性值,而是打印一个2代替,由于我们没有写返回值,所以紧接着返回None,并被print()打印出来

3、demo03

class C:
    def __getattr__(self, name):
        print(1)
        return super().__getattr__(name)

    def __getattribute__(self, name):
        print(2)
        return super().__getattribute__(name)

    def __setattr__(self, name, value):
        print(3)
        super().__setattr__(name, value)

    def __delattr__(self, name):
        print(4)
        super().__delattr__(name)

c = C()
c.x
# 输出以下内容
Traceback (most recent call last):
2
  File "E:/Python Program/test.py", line 128, in <module>
1
    c.x
  File "E:/Python Program/test.py", line 113, in __getattr__
    return super().__getattr__(name)
AttributeError: 'super' object has no attribute '__getattr__'

  首先c.x会先调用getattribute()魔法方法,打印2;然后调用super().getattribute(),找不到属性名x,因此会紧接着调用getattr()魔法方法,于是打印1,然后调用super().getattr()。但是Python会告诉你AttrError,super对象木有getattr()

二、动态设置,获取对象属性

"""
 ------获取对象的信息----

* 判断对象的类型可以用type()
* 如果对象是继承关系的可以用isinstance()
* isinstance(对象,父类)  返回的是True 或者False
* 能用 type()判断的基本类型也可以用 isinstance()判断:

如果要获取一个对象的属性和方法,可以用dir(), 它返回
一个包含字符串的 list

"""

 

class Myobj(object):
    def __init__(self):
        self.x = 9

    def power(self):
        return self.x * self.x

# 定义对象
obj = Myobj()
# 测试对象属性的获取
hasattr(obj, "x")  # 对象里有属性"x"吗 返回True False

print(obj.x)

hasattr(obj, "y")  # 有属性"y"吗

setattr(obj, "y", 19)  # 设置一个属性"y"
print(obj.y)
print(hasattr(obj, "__init__"))


getattr(obj, "y")  # 获取属性"y"

# 如果获取不存在的属性,会抛出AttributeError

# getattr() 还可以传入一个default参数,当获取的属性不存在时,则返回默认值
getattr(obj, "x", 404)

 

三、给实例对象绑定方法

class Student(object):
    pass

s = Student()
# 给对象添加属性
s.name = "Mical"
print(s.name)

# 定义外部函数
def set_age(self, age):
  self.age = age

# 给实例对象绑定方法
from types import MethodType
s.set_age = Method(set_age, s)
s.set_age(25)
print(s.age)


'需要注意的是,给实例对象绑定的方法,对于其他实例是无效的'
'要给所有对象使用外部设定的方法,绑定的就是类'

def set_score(self, score):
    self.score = score
Student.set_score = MethodType(set_score, Student)

# 动态语言能够实现动态绑定,允许我们在程序运行的过程中加功能,

 

"""
__slots__方法可以限制对象仅有的属性
该方法仅对当前类实例起作用,对继承的子类不起作用,
除非子类也定义了,子类实例允许定义的属性就是本身的还有父类的__slots__
"""
class Dog(object):
    __slots__ = ("name", "age")  # 用tuple定义允许绑定的属性名称
    def get(self):
        print(self.name)

d = Dog()

d.name = "Michale"

d.get()
Michale

d.age = 25

d.job = "python"


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-10-c0fc7f775871> in <module>()
----> 1 d.job = "python"

AttributeError: 'Dog' object has no attribute 'job'

 

getattr函数 python python getattr和getattribute_python