第040讲:类和对象:一些相关的BIF

版权声明:转载请标明出处 https://blog.csdn.net/qq_41556318/article/details/84537010

目录

0. 请写下这一节课你学习到的内容:格式不限,回忆并复述是加强记忆的好方式!

测试题

0. 如何判断一个类是否为另一个类的子类?

1. 如何判断对象 a 是否为 类 A 的实例对象?

2. 如何优雅地避免访问对象不存在的属性(不产生异常)?

3. Python 的一些 BIF 很奇怪,但却十分有用。请问 property() 函数的作用是什么?

4. 请补充以下代码,使程序可以正常运行:

5. 通过自学【Python扩展阅读】Python 函数修饰符(装饰器)的使用,使用修饰符修改以下代码。

6. 你真的理解了修饰符的用法吗?那请你写出以下代码没有用上修饰符的等同形式:

7. 通过自学【Python扩展阅读】property 的详细使用方法,将第 4 题的代码修改为“使用属性修饰符创建描述符”的方式实现。


0. 请写下这一节课你学习到的内容:格式不限,回忆并复述是加强记忆的好方式!

今天我们谈谈和类与对象相关的BIF,也就是内置函数。

(一)issubclass(class, classinfo)

如果第一个参数 class 是第二个参数 classinfo 的子类,就返回 True,关于这个函数有几点需要注意的:

  1. 一个类被认为是其自身的子类
  2. classinfo 可以是类对象组成的元组,只要 class 是其中一个候选类的子类,就返回 True

(二)isinstance(object, classinfo)

检查一个实例对象 object 是否属于一个类 classinfo,关于这个函数有几点需要注意的:

  1. 如果第一个参数不是对象,则永远返回 False
  2. 如果第二个参数不是类或者由类对象组成的元组,则抛出一个 TypeError 异常

另外,Python 提供了几个BIF让我们访问对象的属性:

(三)hasattr(object, name)            attr = attribute:属性。

测试一个对象是否有指定的属性。name 要用引号把属性名引起来。

>>> class C:
	def __init__(self, x = 0):
		self.x = x

		
>>> c1 = C()
>>> hasattr(c1, "x")
True
>>> hasattr(c1, x)
Traceback (most recent call last):
  File "<pyshell#71>", line 1, in <module>
    hasattr(c1, x)
NameError: name 'x' is not defined

(四)getattr(object, name[ , default] )       

返回对象指定的属性值。如果指定的属性不存在,如果你有设置 default,它会把这个default 参数打印出来,否则会抛出一个AttributeError异常。

>>> class C:
	def __init__(self, x = 0):
		self.x = x

		
>>> c1 = C()
>>> getattr(c1, 'x')
0
>>> getattr(c1, 'y')
Traceback (most recent call last):
  File "<pyshell#80>", line 1, in <module>
    getattr(c1, 'y')
AttributeError: 'C' object has no attribute 'y'
>>> getattr(c1, 'y', '你所访问的属性不存在')
'你所访问的属性不存在'

(五)setattr(object, name, value)

设定对象中指定属性的值,如果指定的属性不存在,会新建一个新的属性,并给其赋值。

>>> setattr(c1, 'y', '来自江南的你')
>>> getattr(c1, 'y', '你所访问的属性不存在')
'来自江南的你'

(六)delattr(object, name)

删除对象中指定的属性,如果属性不存在,就抛出一个AttributeError异常。

俗话说,条条大路通罗马。Python 其实提供了好几个方式供你选择,property 是一个BIF,作用是通过属性设置属性,

property(fget = None, fset = None, fdel = None, doc = None)

property 函数的作用就是设置一个属性,这个属性就是去设置定义好的属性,它的第一个参数 fget 是获取属性的方法,第一个参数 fset 是设置属性的方法,第一个参数 fdel 是删除属性的方法。举例说明:

>>> class C:
	def __init__(self, size = 10):
		self.size = size
	def getSize(self):
		return self.size
	def setSize(self, value):
		self.size = value
	def delSize(self):
		del self.size
	x = property(getSize, setSize, delSize)

	
>>> c1 = C()
>>> c1.x
10
>>> c1.getSize()
10
>>> c1.x = 18
>>> c1.getSize()
18
>>> c1.setSize(20)
>>> c1.x
20
>>> del c1.x
>>> c1.getSize()
Traceback (most recent call last):
  File "<pyshell#104>", line 1, in <module>
    c1.getSize()
  File "<pyshell#94>", line 5, in getSize
    return self.size
AttributeError: 'C' object has no attribute 'size'

property 的优势:举个例子,在上面这个例子中,这个程序慢慢写的很复杂了,有一天,你想把这个程序进行大改,把函数名进行改写,如果没有 property,那你提供给用户的调用接口就西药修改,就会降低用户体验,但是有了property,问题就不存在了,因为提供给用户的接口都是 x,程序里面无论如何修改,property里面的参数跟着改进行了,用户还是只用调用 x 来设置或者获取 size 属性就可以了。


测试题

0. 如何判断一个类是否为另一个类的子类?

答:使用 issubclass(class, classinfo) 函数,如果第一个参数(class)是第二个参数(classinfo)的一个子类,则返回 True,否则返回 False。
另外以下这些常识你应该知道:

  • 一个类被认为是其自身的子类
  • classinfo 可以是类对象组成的元祖,只要 class 与其中任何一个候选类的子类,则返回 True
  • 在其他情况下,会抛出一个 TypeError 异常

1. 如何判断对象 a 是否为 类 A 的实例对象?

答:使用 isinstance(object, classinfo) 函数,如果第一个参数(object)是第二个参数(classinfo)的实例对象,则返回 True,否则返回 False。
另外以下这些常识你应该知道:

  • 如果 objec t是 classinfo 的子类的一个实例,也符合条件
  • 如果第一个参数不是对象,则永远返回False
  • classinfo 可以是类对象组成的元祖,只要class与其中任何一个候选类的子类,则返回 True
  • 如果第二个参数不是类或者由类对象组成的元祖,会抛出一个 TypeError 异常

2. 如何优雅地避免访问对象不存在的属性(不产生异常)?

答:有两种方法可以做到。
第一种先使用 hasattr(object, name) 函数判断属性是否存在,如果存在再访问(第一个参数(object)是对象,第二个参数(name)是属性名的字符串形式);
第二种方法是直接使用 getattr(object, name[, default]) 函数并设置 default 参数(返回对象指定的属性值,如果指定的属性不存在,返回default(可选参数)的值)。

3. Python 的一些 BIF 很奇怪,但却十分有用。请问 property() 函数的作用是什么?

答:property() 函数允许编程人员轻松、有效地管理属性访问。

4. 请补充以下代码,使程序可以正常运行:

class C:
    def __init__(self, size=10):
        self.size = size

    def getXSize(self):
        return self.size

    def setXSize(self, value):
        self.size = value

    def delXSize(self):
        del self.size

        # 此处应该补充一句代码,程序才能正常运行

>>> c.x
10
>>> c.x = 12
>>> c.x
12

答:x = property(getXSize, setXSize, delXSize)

5. 通过自学【Python扩展阅读】Python 函数修饰符(装饰器)的使用,使用修饰符修改以下代码。

代码A:

class CodeA:
    def foo():
        print("调用静态方法 foo()")

        # 将 foo() 方法设置为静态方法
        foo = staticmethod(foo)

代码B:

class CodeB:
    def foo(cls):
        print("调用类方法 foo()")

        # 将 foo() 方法设置为类方法
        foo = classmethod(foo)

答:其实正是因为设置静态方法和类方法过于讨人吐槽,因此 Python 的作者才开发出了函数修饰符的形式替代。

代码A:

class CodeA:
        @staticmethod
    def foo():
        print("调用静态方法 foo()")

代码B:

class CodeB:
        @classmethod
    def foo(cls):
        print("调用类方法 foo()")

6. 你真的理解了修饰符的用法吗?那请你写出以下代码没有用上修饰符的等同形式:

@something
def f():
    print("I love FishC.com!")

答:其实 Python 的修饰符就是一种优雅的封装,但要注意的是只可以在模块或类定义内对函数进行修饰,不允许修饰一个类。

一个修饰符就是一个函数,它将被修饰的函数做为参数,并返回修饰后的同名函数或其它可调用的东西。

@something
def f():
    print("I love FishC.com!")

# 相当于

def f():
    print("I love FishC.com!")

f = something(f)

7. 通过自学【Python扩展阅读】property 的详细使用方法,将第 4 题的代码修改为“使用属性修饰符创建描述符”的方式实现。

答:可能你还没听说过描述符(这个概念在你学完接下来的几节课自然会了解),但这一点都影响聪明的你修改这个程序。

代码清单:

class C:
    def __init__(self, size=10):
        self.size = size
        
    @property
    def x(self):
        return self.size

    @x.setter
    def x(self, value):
        self.size = value

    @x.deleter
    def x(self):
        del self.size

猜你喜欢

转载自blog.csdn.net/qq_41556318/article/details/84537010
今日推荐