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


    #搬运自FishC论坛,该系列已完结,共有00~96节,本人学习过程中的记录等。

    #FishC论坛:http://bbs.fishc.com/forum.php

    #小甲鱼课程规划帖:http://bbs.fishc.com/thread-1053-1-1.html 此教程适合完全零基础的朋友学习,

    课题笔记

    issubclass()函数

    issubclass()方法用于判断参数 class 是否是类型参数 classinfo 的子类issubclass(class, classinfo),如果 class 是 classinfo 的子类返回 True,否则返回 False。

    它这种检查是属于非严格的检查,1、一个类,他会被认为是自身的子类;2、classinfo可以是类对象组成的元组,只要class是与其中一个候选类的子类,则返回True,一个一个检索过去,其他类型就会抛出Type Error

    >>> class A:
        pass
    
    >>> class B:
        pass
    
    >>> issubclass(B, A)
    False
    >>> class B(A):
        pass
    
    >>> issubclass(B, A)
    True
    >>> issubclass(B, B)
    True
    >>> issubclass(B, object)
    True
    >>> #object是所有类的一个基类

    isinstance() 函数

    isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。

    isinstance() 与 type() 区别:

    type() 不会认为子类是一种父类类型,不考虑继承关系。

    isinstance() 会认为子类是一种父类类型,考虑继承关系。

    如果要判断两个类型是否相同推荐使用 isinstance()。

    用法:isinstance(object, classinfo)     object -- 实例对象,classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。

    注意:1、如果第一个参数不是对象,则永远返回False;2、如果第二个参数不是由类对象组成的元组,会抛出个TypeError异常。

    hasattr() 函数

    hasattr() 函数用于判断对象是否包含对应的属性。语法:hasattr(object, name),object -- 对象。name -- 字符串,属性名。如果对象有该属性返回 True,否则返回 False。

    getattr() 函数

    getattr()函数用于返回一个对象属性值。语法:getattr(object, name[, default])   object -- 对象,name -- 字符串,对象属性,default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。返回对象属性值。例子:

    >>>class A(object):
    ...     bar = 1
    ... 
    >>> a = A()
    >>> getattr(a, 'bar')        # 获取属性 bar 值
    1
    >>> getattr(a, 'bar2')       # 属性 bar2 不存在,触发异常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'A' object has no attribute 'bar2'
    >>> getattr(a, 'bar2', 3)    # 属性 bar2 不存在,但设置了默认值
    3
    >>>

    setattr() 函数

    setattr() 函数对应函数 getattr(),用于设置属性值,该属性不一定是存在的。语法:setattr(object, name, value) object -- 对象,name -- 字符串,对象属性,value -- 属性值。无返回值。例子:

    对已存在的属性进行赋值:

    >>>class A(object):
    ...     bar = 1
    ... 
    >>> a = A()
    >>> getattr(a, 'bar')          # 获取属性 bar 值
    1
    >>> setattr(a, 'bar', 5)       # 设置属性 bar 值
    >>> a.bar
    5

    如果属性不存在会创建一个新的对象属性,并对属性赋值:

    >>>class A():
    ...     name = "runoob"
    ... 
    >>> a = A()
    >>> setattr(a, "age", 28)
    >>> print(a.age)
    28
    >>>

    delattr() 函数

    delattr 函数用于删除属性delattr(x, 'foobar') 相等于 del x.foobar。语法:delattr(object, name) object -- 对象,name -- 必须是对象的属性。无返回值。例子:

    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
     
    class Coordinate:
        x = 10
        y = -5
        z = 0
     
    point1 = Coordinate() 
     
    print('x = ',point1.x)
    print('y = ',point1.y)
    print('z = ',point1.z)
     
    delattr(Coordinate, 'z')
     
    print('--删除 z 属性后--')
    print('x = ',point1.x)
    print('y = ',point1.y)
     
    # 触发错误
    print('z = ',point1.z)

    结果:

    ('x = ', 10)
    ('y = ', -5)
    ('z = ', 0)
    --删除 z 属性后--
    ('x = ', 10)
    ('y = ', -5)
    Traceback (most recent call last):
      File "test.py", line 22, in <module>
        print('z = ',point1.z)
    AttributeError: Coordinate instance has no attribute 'z'

    property() 函数

    property() 函数的作用是在新式类中返回属性值。用属性来设置属性。语法:class property([fget[, fset[, fdel[, doc]]]])  or property(fget = None, fset = None, fdel = None, doc = None)

    参数:fget -- 获取属性值的函数;fset -- 设置属性值的函数;fdel -- 删除属性值函数;doc -- 属性描述信息

    返回新式类属性。

    property()这个函数的作用就是设置一个属性,这个属性的作用是去设置定义好的属性。x如何设置属性,你必须传入写好的方法,第一个属性是获取属性的方法,第二个是设置属性的方法,第三是删除属性的方法,第四个就文档。c1.x 就会执行第一个参数的内容,就是获取方法了,c1.x = .. 等于什么的时候就会调用第二个方法。小甲鱼例子:

    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.getSize()
    10
    >>> c1.x
    10
    >>> c1.x = 18
    >>> c1.x
    18
    >>> c1.size
    18
    >>> c1.getSize()
    18
    >>> del c1.x
    >>> c1.size
    Traceback (most recent call last):
      File "<pyshell#19>", line 1, in <module>
        c1.size
    AttributeError: 'C' object has no attribute 'size'
    >>> 

    菜鸟教程例子:

    定义一个可控属性值 x:

    class C(object):
        def __init__(self):
            self._x = None
     
        def getx(self):
            return self._x
     
        def setx(self, value):
            self._x = value
     
        def delx(self):
            del self._x
     
        x = property(getx, setx, delx, "I'm the 'x' property.")

    如果 cC 的实例化, c.x 将触发 getter 就是property的第一个参数,第一个参数的方法是getattr;而c.x = value 将触发 setter 就是第二个方法,设置;  del c.x 触发 deleter。

    如果给定 doc 参数,其将成为这个属性值的 docstring,否则 property 函数就会复制 fget 函数的 docstring(如果有的话)

    这段装饰器的还不会!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    将 property 函数用作装饰器可以很方便的创建只读属性

    class Parrot(object):
        def __init__(self):
            self._voltage = 100000
     
        @property
        def voltage(self):
            """Get the current voltage."""
            return self._voltage

    上面的代码将 voltage() 方法转化成同名只读属性的 getter 方法。

    property 的 getter,setter 和 deleter 方法同样可以用作装饰器:

    class C(object):
        def __init__(self):
            self._x = None
     
        @property
        def x(self):
            """I'm the 'x' property."""
            return self._x
     
        @x.setter
        def x(self, value):
            self._x = value
     
        @x.deleter
        def x(self):
            del self._x

    这个代码和第一个例子完全相同,但要注意这些额外函数的名字和 property 下的一样,例如这里的 x。

    课后测试题及答案

    测试题:

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

    使用issubclass()函数,例如issubclass(A, B),A是否是B的子类呢

    答:使用 issubclass(class, classinfo) 函数,如果第一个参数(class)是第二个参数(classinfo)的一个子类,则返回 True,否则返回 False。

    另外以下这些常识你应该知道:

    1、一个类被认为是其自身的子类

    2、classinfo 可以是类对象组成的元祖,只要 class 与其中任何一个候选类的子类,则返回 True

    3、在其他情况下,会抛出一个 TypeError 异常

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

    使用isinstance()函数

    答:使用 isinstance(object, classinfo) 函数,如果第一个参数(object)是第二个参数(classinfo)的实例对象,则返回 True,否则返回 False。 

    另外以下这些常识你应该知道:

    1、如果 objec t是 classinfo 的子类的一个实例,也符合条件

    2、如果第一个参数不是对象,则永远返回False

    3、classinfo 可以是类对象组成的元祖,只要class与其中任何一个候选类的子类,则返回 True

    4、如果第二个参数不是类或者由类对象组成的元祖,会抛出一个 TypeError 异常

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

    使用hasattr()

    答:有两种方法可以做到。第一种先使用 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
    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
    
            # 此处应该补充一句代码,程序才能正常运行
        x = property(getXSize, setXSize, delXSize)#property的参数是字符串,方法名就ok了
    # >>> c.x
    # 10
    # >>> c.x = 12
    # >>> c.x
    # 12

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

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

    代码A:

    class CodeA:
        def foo():
            print("调用静态方法 foo()")
    
            # 将 foo() 方法设置为静态方法
            foo = staticmethod(foo)
    代码A

    答案:

    代码B:

    class CodeB:
        def foo(cls):
            print("调用类方法 foo()")
    
            # 将 foo() 方法设置为类方法
            foo = classmethod(foo)
    代码B

    答:其实正是因为设置静态方法和类方法过于讨人吐槽,因此 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. 通过自学【扩展阅读】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

    作者:Agiroy_70

    本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。

    博主的文章主要是记录一些学习笔记、作业等。文章来源也已表明,由于博主的水平不高,不足和错误之处在所难免,希望大家能够批评指出。

    博主是利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的文章,请原谅博主成为一个无耻的文档搬运工!

  • 相关阅读:
    RDLC报表开发技巧备忘
    C#3.0"扩展方法"简记
    将activity转化成view
    取消logcat输出
    低栏的项目切换
    android edittext 限制文本框输入的长度和提示信息
    android如何调用dotnet编写的webservice
    iphone 式退出
    几种tabhost的总结(1)
    切换浏览示意图
  • 原文地址:https://www.cnblogs.com/hale547/p/13360814.html
Copyright © 2020-2023  润新知