hasattr()、setattr()、getattr() 详细介绍

hasattr() 函数

hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法

hasattr(object, name)
  • obj 指的是某个类的实例对象
  • name 表示指定的属性名或方法名

返回值

  • 实例对象中包含有相应的属性或方法则返回 True,否则返回 False
class CLanguage:
    age = 1
    def __init__ (self):
        self.name = "C语言中文网"
        self.add = "123"
    def say(self):
        print("我正在学Python")

clangs = CLanguage()
print(hasattr(clangs,"age")) # True
print(hasattr(clangs,"name")) # True
print(hasattr(clangs,"add")) # True
print(hasattr(clangs,"say")) # True
print(hasattr(clangs,"out")) # False
True
True
True
True
False

显然,无论是属性名还是方法名,都在 hasattr() 函数的匹配范围内。因此,只能通过该函数判断实例对象是否包含该名称的属性或方法,但不能精确判断,该名称代表的是属性还是方法。

getattr() 函数

getattr() 函数获取某个类实例对象中指定属性的值。没错,和 hasattr() 函数不同,该函数只会从类对象包含的所有属性中进行查找。

getattr(obj, name[, default])
  • object – 对象
  • name – 字符串,对象属性
  • default – 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。

返回值

  • 返回对象的属性值
class CLanguage:
    def __init__ (self):
        self.name = "xiaoming"
        self.add = "net"
    def say(self):
        print("我正在学Python")

clangs = CLanguage()
print(getattr(clangs,"name"))
print(getattr(clangs,"add"))
print(getattr(clangs,"say"))
print(getattr(clangs,"display",'nodisplay'))
xiaoming
net
<bound method CLanguage.say of <__main__.CLanguage object at 0x00000209F0511490>>
nodisplay

思考?

既然 getattr(clangs,'name')clangs.name 都能获取 clangs 对象的 name 属性的值,那使用后者不就行了吗?毕竟点语法看起来比 getattr 函数简单多了,不用写那么多字。确实,一般情况下,使用点语法来获取属性值非常方便。但是也存在一些场景,点语法无能为力,只好使用 getattr 函数来获取属性值。

究竟应该使用谁,关键就在于,编写代码的时候程序员是否能够确定要获取哪个属性的值。

如果明确地知道,就是想要获取 age 这个属性的值,那么 clangs.name 就满足了我的需求。但是,试想如下的场景:

clangs 对象有 name,age,job,weight,height 五个属性,要根据用户的选择来展示相应的属性。也就是说,用户告诉程序“给我看看 clangs 的身高吧!”,程序就要把 height 属性的值展示给用户看。

上面这个场景中,程序员写代码的时候无法确定要访问哪个属性值,选择权是交给用户的。而用户的输入是一个字符串 “height”,字符串在 clangs .height 这样的点语法里并没有容身之处。怎么样?这个需求用点语法不太合适了吧?(如果非要用点语法,也不是不可以。比如,用一个字典把 clangs 所有的属性值都存起来。键就是 “height” 这样的字符串,值就是 clangs.height 这样的属性值。那么,就可以用 “height" 这样的字符串把对应的属性值取出来了。不过这个方法没有接下来要说到的 getattr 好。)这时候,用 getattr 就非常合适了。因为,getattr 的第二个参数类型正是字符串!可以用 getattr(clangs,“height”) 来取出身高的值。甚至还可以使用default参数很好地解决用户输入的属性不存在的问题。

from typing import NamedTuple


class CLanguage(NamedTuple):
    '''人类'''
    name: str
    age: int
    job: str
    weight: float
    height: float

clangs  = CLanguage('clangs', 32, 'actor', 60, 178)

# 把用户输入的字符串赋值给变量attribute_name
attribute_name = input('''What do you want to know about clangs? 
Enter an attribute name>>>''')
# 注意,上述字符串被传进了这个函数作为第二个参数
# 第三个参数是属性不存在时返回的字符串
print(getattr(clangs , attribute_name, 'Sorry, this attribute does not exist.'))

两种表达式的区别

  • 第一种,getattr(obj,"_attr")
  • 第二种,getattr(obj,"_" + attr)
  • 第一种只能访问_attr属性,而第二种可以访问所有带下划线的属性
class Student:  # 定义类
	def __init__(self,name,identity,age):
		self._name = name
		self._identity = identity
		self.age = age
	def __getitem__(self,item):
		if isinstance(item,str):
			return getattr(self,"_item")

st=Student("Huang Lei",1323010212,12)  # 实例化

print(st["age"])
AttributeError: 'Student' object has no attribute '_item'
print(st["name"]
AttributeError: 'Student' object has no attribute '_item'

上面方式只能访问 '_item' 属性。不论是否是带下划线的属性。

class Student:
	def __init__(self,name,identity,age):
		self._name = name
		self._identity = identity
		self.age = age
	def __getitem__(self,item):
		if isinstance(item,str):
			return getattr(self,"_" + item)

st=Student("Huang Lei",1323010212,12)

print(st["age"])
AttributeError: 'Student' object has no attribute '_age'
print(st["name"])
Huang Lei

setattr()函数

setattr() 函数的功能相对比较复杂,它最基础的功能是修改类实例对象中的属性值。其次,它还可以实现为实例对象动态添加属性或者方法。

setattr(obj, name, value)
class CLanguage:
    def __init__ (self):
        self.name = "xiaoming"
        self.add = "net"
    def say(self):
        print("我正在学Python")

clangs = CLanguage()
print(clangs.name)
print(clangs.add)
setattr(clangs, "name", "Python教程")
setattr(clangs, "add", "python")
print(clangs.name)
print(clangs.add)
xiaoming
net
Python教程
python

利用 setattr() 函数,还可以将类属性修改为一个类方法,同样也可以将类方法修改成一个类属性

def say(self):
    print("我正在学Python")

class CLanguage:
    def __init__ (self):
        self.name = "xiaoming"
        self.add = "net"
clangs = CLanguage()
print(clangs.name)
print(clangs.add)
setattr(clangs, "name", say)
clangs.name(clangs)
xiaoming
net
我正在学Python

显然,通过修改 name 属性的值为 say(这是一个外部定义的函数),原来的 name 属性就变成了一个 name() 方法。

使用 setattr() 函数对实例对象中执行名称的属性或方法进行修改时,如果该名称查找失败,Python 解释器不会报错,而是会给该实例对象动态添加一个指定名称的属性或方法

def say(self):
    print("我正在学Python")
class CLanguage:
    pass

clangs = CLanguage()
setattr(clangs, "name", "xiaoming")
setattr(clangs, "say", say)
print(clangs.name)
clangs.say(clangs)
xiaoming
我正在学Python

References

【python】hasattr( )的用法

Python setattr()、getattr()、hasattr()函数用法详解

python中getattr()的用法

getattr 函数详讲

你可能感兴趣的:(#,Python,python,数学建模,开发语言)