Python 常用内置函数详解(八):对象属性操作getattr()、setattr()、delattr()、hasattr()、vars()函数详解
目录
- 一、功能
- 二、语法和示例
- 三、其他常用属性操作相关的内置函数
- 3.1 setattr()函数——设置对象的属性值
- 3.2 delattr()函数——删除对象的属性
- 3.3 hasattr()函数——检查对象是否含有属性
- 3.4 vars()函数——获取对象的属性和属性值
一、功能
getattr()函数——获取对象的属性值
二、语法和示例
getattr() 函数的语法格式如下:
getattr(object, name[, default])
参数说明:
1.object: 对象
2.name: 字符串,对象属性
3.default: 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError
4.返回值: 返回对象属性
【示例1】使用getattr()函数获取实例对象属性值,代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:34
# @Author : AmoXiang
# @File : getattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Student(object):name = 'Andy'age = 18def hello(self):return 'hello's = Student()
print(getattr(Student, 'name'))
f = getattr(s, 'hello')
print(getattr(s, 'name'))
print(getattr(s, 'age'))
print(getattr(s, 'gender', '男'))
print(f())
【示例2】使用try-except 语句捕获getattr()函数获取属性失败时的异常,代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:34
# @Author : AmoXiang
# @File : getattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Student:name = 'Andy'age = 18s = Student() # 实例化Student类# 捕获属性异常
try:print(getattr(s, 'gender'))
except AttributeError:print('没有该属性')
【示例3】使用多种方式打开文件。创建一个类,根据接受到的参数,以不同的方式打开文件。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:34
# @Author : AmoXiang
# @File : getattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Dbf(object):def __init__(self, f, read_only=False, new=False):if isinstance(f, str):# 如果是文件self.name = fif new:# 如果new参数为真,以写入二进制方式打开self.stream = open(f, "w+b")else:# 否则,以二进制读的方式打开self.stream = open(f, ("r+b", "rb")[bool(read_only)])else:# 如果是数据流self.name = getattr(f, "name", "") # 获取stream的name属性,赋值给实例属性self.stream = f # 将stream赋值给实例属性dbf = Dbf('hello.txt') # 传递文件名
print(dbf.stream)
stream = open('hello.txt', 'r+b') # 打开文件
new_dbf = Dbf(stream) # 传递stream数据流
print(new_dbf.stream)
print('文件名是{}'.format(new_dbf.name))
【示例4】实现“授权”的功能。所谓授权,是指包装一个数据类型,通常是对已存在的类型的一些定制。这种做法可以新建、修改或删除原有产品的功能,其他属性则保持原样。授权的过程,即是所有新增的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。实现授权的关键点就是覆盖 __getattr__
()方法。下面实现对一个文件句柄类型进行“授权”。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:34
# @Author : AmoXiang
# @File : getattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680import timeclass FileHandle:""" '授权' 类 """def __init__(self, filename, mode='r', encoding='utf-8'):# 对一个文件句柄进行"授权"self.file = open(filename, mode, encoding=encoding)def write(self, line): # 新增的功能t = time.strftime('%Y-%m-%d %T')self.file.write('%s %s' % (t, line))def __getattr__(self, item): # 保留原有的功能return getattr(self.file, item)f1 = FileHandle('test.txt', 'w+') # 创建"授权"类对象
f1.write('Hello 5.1节!') # 写入数据
f1.seek(0) # 定位光标
print(f1.read()) # 读取数据
f1.close() # 关闭文件句柄
【示例5】在实现“授权”功能的基础之上,对文件句柄类型添加 'b'
模式的支持。从此再在写入数据时,不管是对于字符串还是字节数据,都直接可以写入,不需再去关注数据写入的数据格式。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:34
# @Author : AmoXiang
# @File : getattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class FileHandle:def __init__(self, filename, mode='r', encoding='utf-8'):if 'b' in mode:self.file = open(filename, mode) # 'b'模式不加编码方式else:self.file = open(filename, mode, encoding=encoding)self.filename = filenameself.mode = modeself.encoding = encodingdef write(self, line):if 'b' in self.mode:if not isinstance(line, bytes): # 添加类型检查self.file.write(line.encode(self.encoding))else:self.file.write(line)def __getattr__(self, item): # 新增的功能return getattr(self.file, item)def __str__(self):if 'b' in self.mode:res = "<_io.BufferedReader name='%s'>" % self.filenameelse:res = "<_io.TextIOWrapper name='%s' mode='%s' encoding='%s'>" % \(self.filename, self.mode, self.encoding)return resf1 = FileHandle('test2.txt', 'wb')
# 自定制的 write()方法, 不需再手动进行encode, 使用更加方便。
f1.write('你好啊 2025-05-01!')
f1.write(' Amo老师 ')
print(f1)
f1.close() # 关闭文件句柄,释放资源
三、其他常用属性操作相关的内置函数
3.1 setattr()函数——设置对象的属性值
setattr 函数的语法格式如下:
参数说明:
- object:对象
- name:字符串,对象属性
- value:属性值
- 返回值:无
【示例1】使用setattr()函数替换实例中已经存在的属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:11
# @Author : AmoXiang
# @File : setattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Student:name = 'Andy'age = 18s = Student()
print(getattr(s, 'name')) # Andy
setattr(s, 'name', 'Jack')
print(getattr(s, 'name')) # Jack
【示例2】使用setattr()函数为实例对象创建新的属性,代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:11
# @Author : AmoXiang
# @File : setattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Student:name = 'Andy'age = 18s = Student()if getattr(s, 'gender', None) is None:setattr(s, 'gender', '男')gender = getattr(s, 'gender')
print(gender)
【示例3】结合字典的键值对,使用setattr()函数为实例对象批量创建属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:11
# @Author : AmoXiang
# @File : setattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Student(object):def __init__(self, **dic):for attr, value in dic.items():setattr(self, attr, value)dict_val = {'name': 'Andy', 'age': 18, 'gender': '男'}
s = Student(**dict_val)print(s.name)
print(s.age)
print(s.gender)
【示例4】根据HTTP响应状态码描述获取状态码数值。HTTP 响应状态代码指示特定HTTP请求是否已成功完成。例如请求返回“404 Not Found”,其中“404”为状态码,“Not Found”为状态描述。下面的程序可以实现根据状态描述获取状态码,代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:11
# @Author : AmoXiang
# @File : setattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680_codes = {# 定义HTTP响应码200: ('ok', 'okay', 'all_ok', 'all_okay', 'all_good', '\\o/', '✓'),400: ('bad_request', 'bad'),401: ('unauthorized',),403: ('forbidden',),404: ('not_found', '-o-'),500: ('internal_server_error', 'server_error', '/o\\', '✗'),
}class LookupDict(object):passcodes = LookupDict()def get_code():for code, titles in _codes.items(): # 遍历响应码for title in titles: # 遍历字典的值setattr(codes, title, code) # 将其赋值为实例的title属性if not title.startswith(('\\', '/')): # 处理特殊字符串setattr(codes, title.upper(), code)get_code() # 调用函数
# 输出对应的响应码
print(codes.ok)
print(codes.okay)
print(codes.not_found)
print(codes.server_error)
【示例5】除了可以为类添加属性外,还可以为其动态添加方法,并可以通过实例调用该方法进行相关的逻辑操作。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:11
# @Author : AmoXiang
# @File : setattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Geek:name = 'C灵C'def __init__(self, age):self.age = agedef ge_msg(raspberry, gender):print(raspberry)return gendersetattr(Geek, 'gender_msg', classmethod(ge_msg)) # 向类中添加一个方法,命名为gender_msg
g = Geek(23)
print('name: %s, age: %s, gender: %s' % (g.name, g.age, g.gender_msg('male')))
3.2 delattr()函数——删除对象的属性
delattr 函数的语法格式如下:
参数说明:
- object:对象
- name:字符串,希望删除属性的名称
- 返回值:None
说明: delattr(x, 'foobar')
相等于 del x.foobar, 删除不存在的属性会报错。
【示例1】删除类属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:05
# @Author : AmoXiang
# @File : delattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Student:name = 'Andy'age = 18def __str__(self):return "name: {}, age = {}".format(self.name, self.age)# Before: ['__module__', 'name', 'age', '__str__', '__dict__', '__weakref__', '__doc__']
print("Before:", list(Student.__dict__))
try:delattr(Student, 'age') # 删除类属性
except AttributeError as e:print('该类 age 属性不存在:', e)
# Middle: ['__module__', 'name', '__str__', '__dict__', '__weakref__', '__doc__']
print("Middle:", list(Student.__dict__))
delattr(Student, "__str__") # 删除类方法
try:delattr(Student, '__init__') # 所删除属性不存在,则报错
except AttributeError as e:# 该类的 __init__ 属性不存在 : type object 'Student' has no attribute '__init__'print('该类的 __init__ 属性不存在 :', e)
# End: ['__module__', 'name', '__dict__', '__weakref__', '__doc__']
print("End: ", list(Student.__dict__))
【示例2】使用delattr()函数删除对象属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:05
# @Author : AmoXiang
# @File : delattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Student:name = 'Andy'age = 18def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return "name: {}, age = {}".format(self.name, self.age)obj = Student("amo", 18) # 创建学生对象
print("Before:", list(obj.__dict__))
try:delattr(obj, 'age') # 删除对象属性
except AttributeError as e:print('该类对象 age 属性不存在:', e)
print("Middle:", list(obj.__dict__))
try:delattr(obj, 'salary') # 所删除属性不存在, 则报错
except AttributeError as e:print('该类对象的 salary 属性不存在 :', e)
print("End: ", list(obj.__dict__))
【示例3】使用delattr()函数删除模块对象的属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:05
# @Author : AmoXiang
# @File : delattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680import sysclass Student:name = 'Andy'age = 18obj = sys.modules[__name__] # 获取当前模块对象
print("Before:", list(obj.__dict__))
try:delattr(obj, 'Student') # 删除模块对象属性——Student 类
except AttributeError as e:print('该模块对象 Student 属性不存在:', e)
print("Middle:", list(obj.__dict__))
try:delattr(obj, 'salary') # 所删除属性不存在, 则报错
except AttributeError as e:print('该模块对象的 salary 属性不存在 :', e)
print("End: ", list(obj.__dict__))
【示例4】使用delattr()函数删除子类所继承的属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:05
# @Author : AmoXiang
# @File : delattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class School: # 父类father = 100def __init__(self):self.position = "ChongQing City"self.level = "first to first"class Student(School): # 子类son = 200def __init__(self):# 执行父类 __init__() 方法super(Student, self).__init__()self.name = "amo"self.age = 100obj = Student() # 创建子类对象
print("Before:", list(obj.__dict__))
try:delattr(obj, 'level') # 删除子类对象所继承的实例属性——level
except AttributeError as e:print('该对象继承的 level 属性不存在:', e)
print("Middle:", list(obj.__dict__))
print("子类对象获取父类类属性 father = ", obj.father)
print("使用子类类名获取父类的类属性:father = ", Student.father)
try:delattr(obj, 'father') # 删除子类对象所继承的类属性时报错,
except AttributeError as e:print('该对象的 father 属性不存在 :', e)
try:delattr(Student, 'father') # 删除子类所继承的父类的类属性时报错,
except AttributeError as e:print('该类父类的 father 属性不存在 :', e)
print("End: ", list(obj.__dict__))
【示例5】删除新增的类和实例属性。Python是一个非常具有活力的动态语言,其在运行时可以根据需求改变结构,例如动态添加和删除类与实例的属性和方法,具体方法可参考如下代码:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:05
# @Author : AmoXiang
# @File : delattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Person(object):sex = 'male' # 类属性def __init__(self, name):self.name = namep = Person("jerry") # 生成一个实例
print("My name is %s,My sex is %s" % (p.name, p.sex))
p.age = 23 # 定义类的新属性
print("My age is:", p.age)
delattr(p, "age") # 删除实例属性
delattr(Person, "sex") # 删除类属性# 下面代码会报AttributeError,因为age和sex两个属性已成功删除
print("My age is %s,My sex is %s" % (p.age, p.sex))
【示例6】delattr()函数的功能基本同 del运算符一致,仅多了一条动态属性删除的功能。除此之外,可以使用 del 运算符来实现相同的删除效果,并且占用的字节码指令更少,执行速度更高。测试代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 9:05
# @Author : AmoXiang
# @File : delattr_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Person(object):name = 'C灵C' # 类属性p = Person() # 生成一个实例
for i in range(1000): # 生成测试数据a = 'attr_' + str(i)setattr(p, a, i) # 设置新属性note = input('请选择删除方法(1.delattr()函数, 2.del运算符):')
if note == '1':for j in range(1000):k = 'attr_' + str(j)delattr(p, k) # 动态删除属性print('delattr()函数已完成删除') # 在测试效率时,尽量不要包含print()函数
elif note == '2':for j in range(1000):k = 'attr_' + str(j)del p.k # 此行代码会报AttributeError错误,不能动态删除属性print('del运算符已完成删除')
3.3 hasattr()函数——检查对象是否含有属性
hasattr 函数的语法格式如下:
参数说明:
- object:对象
- name:字符串,属性名
- 返回值:如果对象有该属性返回 True,否则返回 False
【示例1】使用hasattr()函数判断是否属性为原生类型属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:50
# @Author : AmoXiang
# @File : hasattr.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680str_val = 'hasattr'
print(hasattr(str_val, '__len__')) # 输出为True
print(hasattr(str_val, '__lt__')) # 输出为True
print(hasattr(str_val, 'format')) # 输出为True
print(hasattr(str_val, 'lower')) # 输出为Truelist_val = [1, 2, 3]
print(hasattr(list_val, '__len__')) # 输出为True
print(hasattr(list_val, '__delitem__')) # 输出为True
print(hasattr(list_val, 'pop')) # 输出为Truedict_val = {'name': 'Andy'}
print(hasattr(dict_val, '__len__')) # 输出为True
print(hasattr(dict_val, 'keys')) # 输出为True
print(hasattr(dict_val, 'values')) # 输出为True
【示例2】使用hasattr()函数判断属性是否为类属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:50
# @Author : AmoXiang
# @File : hasattr.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Student:name = 'Andy'age = 18def hello(self):print('hello')print(hasattr(Student, 'name')) # True
print(hasattr(Student, 'age')) # True
print(hasattr(Student, 'hello')) # True
print(hasattr(Student, 'hi')) # False
【示例3】使用hasattr()函数判断是否为实例属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:50
# @Author : AmoXiang
# @File : hasattr.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Student:name = 'Andy'age = 18def hello(self):print('hello')s = Student()
# 判断是否属于实例的属性
print(hasattr(s, 'name')) # True
print(hasattr(s, 'age')) # True
print(hasattr(s, 'hello')) # True
print(hasattr(s, 'hi')) # False
【示例4】使用hasattr()函数判断属性是否继承父类属性。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:50
# @Author : AmoXiang
# @File : hasattr.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class A:a_name = 'A'def a_test(self):passclass B(A):b_name = 'B'def b_test(self):passprint(hasattr(B, 'a_name')) # True
print(hasattr(B, 'a_test')) # True
print(dir(B()))
【示例5】获取表格每列的宽度。在绘制表格时,为了使表格展示美观,通常需要获取每一列中的最长宽度,然后再绘制表格。如果该表格有表头,那么每一列的最长宽度可能是表头的长度,也可能是表格中内容的长度。下面的代码可以实现该功能:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:50
# @Author : AmoXiang
# @File : hasattr.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680def _max_word_len(text):'''获取单词的最大长度'''return max((len(word) for word in text.split()))def _get_column_string_lengths(dataset):"""返回每一列的字符串长度和该列的字符串长度最大值"""if dataset.headers: # 判断表头是否存在# 获取表头列的长度column_lengths = [[len(h)] for h in dataset.headers]# 获取表头每列的单词长度word_lens = [_max_word_len(h) for h in dataset.headers]for row in dataset.dict: # 遍历每一行# 如果row对象包含values属性,则创建生成器values = iter(row.values() if hasattr(row, 'values') else row)# 遍历字典的值for i, val in enumerate(values):text = str(val) # 转化为字符串column_lengths[i].append(len(text)) # 加入列表word_lens[i] = max(word_lens[i], _max_word_len(text)) # 获取最大长度return column_lengths, word_lensclass Dateset(object):passds1 = Dateset() # 实例化Dateset类
ds1.headers = ("first_name", "last_name", "age") # 动态条件headers属性
# 动态添加dict属性
ds1.dict = [{'first_name': 'andy', 'last_name': 'feng', 'age': 18},{'first_name': 'Alexandra', 'last_name': 'Gwenhwyfar', 'age': 30}]
# 输出每列的字符串长度,以及字符串长度的最大值
print(_get_column_string_lengths(ds1))
# ([[10, 4, 9], [9, 4, 10], [3, 2, 2]], [10, 10, 3])
# 说明: 在运行结果的列表中,有2个元素。第1个元素是每1列的长度(包括表头、内容的长度),第2个是元素是第1列的最大值。
【示例6】在操作一些特殊文件时,通常需要判断一个文件是否具备读写的权限。可以通过hasattr()函数来实现该功能。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 8:50
# @Author : AmoXiang
# @File : hasattr.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class FileProxyMixin:def __init__(self, file):"""初始化方法:param file: 文件对象"""self.file = file@propertydef closed(self):return not self.file or self.file.closeddef readable(self):# 如果文件关闭,返回Falseif self.closed:return False# 判断是否有'readable'属性if hasattr(self.file, 'readable'):return self.file.readable()return Truedef writeable(self):# 如果文件关闭,返回Falseif self.closed:return False# 判断是否有'writeable'属性if hasattr(self.file, 'writeable'):return self.file.writable()return 'w' in getattr(self.file, 'mode', '')if __name__ == "__main__":file_name = 'hello.txt'# 判断文件是否可读with open(file_name) as f:file = FileProxyMixin(f)if file.readable():print(f'{file_name}文件是可读文件')else:print(f'{file_name}文件是不可读文件')# 判断关闭文件后,是否可写with open(file_name) as f:# 关闭文件print('关闭文件')f.close()file = FileProxyMixin(f)# 判断是否可写if file.writeable():print(f'{file_name}文件是可写文件')else:print(f'{file_name}文件是不可写文件')
3.4 vars()函数——获取对象的属性和属性值
vars 函数的语法格式如下:
参数说明:
- object:对象
- 返回值:如果没有实参,则返回当前本地作用域中的属性和属性值的字典对象;如果有实参,则返回该对象 object 的属性和属性值的字典对象
【示例1】vars()函数在类继承中的表示。使用vars()函数分别输出子类、子类对象、父类、父类对象的属性字典对象。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 18:04
# @Author : AmoXiang
# @File : vars_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680class Leg: # 父类num = 2def __init__(self):self.is_sickness = Falseclass Person(Leg): # 子类posi = "ChongQing"def __init__(self):super(Person, self).__init__()self.salary = 500000person = Person() # 创建子类对象
leg = Leg()
obj_01, obj_02 = vars(Person), vars(person)
obj_03, obj_04 = vars(Leg), vars(leg)
print(" 子类 vars() = {} \n子类对象vars() = {}".format(obj_01, obj_02))
print(" 父类 vars() = {} \n父类对象vars() = {}".format(obj_03, obj_04))
print(obj_02["is_sickness"]) # 获取属性值
obj_02["is_sickness"] = True # 修改属性值
print(obj_02["is_sickness"])
【示例2】vars()与类的 __dict__
属性。在 Python中,类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都放在类的 __dict__
属性里,但一些内置的数据类型是没有 __dict__
属性的。若在使用vars()函数时传入自定义类(大多数自定义类会隐式创建 __dict__
属性)的对象,则返回对象的 __dict__
属性;若传入一些内置的数据类型,则由于其没有 __dict__
属性,就会提示 TypeError 错误。代码如下:
# -*- coding: utf-8 -*-
# @Time : 2025-05-01 18:04
# @Author : AmoXiang
# @File : vars_demo.py
# @Software: PyCharm
# @Blog: https://blog.csdn.net/xw1680x = 1
a = vars() # 未传入参数,作用相当于locals()
if a == locals():b = a['x']print(b)class VarsDict:def __init__(self):self.__dict__ = {'': '调用了__dict__属性'}c = VarsDict()
d = vars(c) # 返回字典对象
print(d)
vars(True) # 传入Python内置的数据类型,由于内置的数据类型是没有__dict__属性,所以此处会报TypeError错误