面向对象编程04

本文介绍了Python面向对象编程中类与实例的关系,包括issubclass()和isinstance()的使用,type()和dir()的功能,属性的增删改查方法,算数运算符的重载,以及__str__()和__repr__()的差异和作用。通过这些内容,读者可以深入理解Python面向对象编程中的核心概念和操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

issubclass()与isinstance()

  • sisubclass()用于判断类对象与类对象之间的关系(类对象前面的类是不是后面的子类),输出逻辑变量(true、false)

接收两个实参,第一个实参是类对象;第二个实参是类对象或由类对象组成的元组

class A(object):
    pass
class B(object):
    pass
class C(object):
    pass
class D(A):
    pass

当第二个实参是类对象时,如果第一个实参是第二个实参的子类,那么返回True

In [4]: issubclass(D, A)
Out[4]: True
In [5]: issubclass(D, B)
Out[5]: False

当第二个实参是类对象组成的元组时,如果第一个实参是第二个实参中任意一个类对象的子类,返回True

In [6]: issubclass(D, (B, A, C))
Out[6]: True
In [7]: issubclass(D, (B, C))
Out[7]: False

布尔类型是整数类型的子类,不是字符串类型的子类

In [8]: issubclass(bool, int)
Out[8]: True
In [9]: issubclass(bool, str)
Out[9]: False
In [10]: issubclass(bool, (str, int, dict))
Out[10]: True
In [11]: issubclass(bool, (str, list, dict))
Out[11]: False
  • isinstance()用于判断实例对象与类对象之间的关系

接收两个实参,第一个实参是实例对象;第二个实参是类对象或由类对象组成的元组

class A(object):
    pass
class B(object):
    pass
class C(object):
    pass
class D(A):
    pass

当第二个实参是类对象时,如果第一个实参是第二个实参的实例对象,或者第一个实参是第二个实参的子类的实例对象,那么返回True

In [13]: isinstance(D(), D)
Out[13]: True
In [14]: isinstance(D(), A)
Out[14]: True

当第二个实参是类对象组成的元组时,如果第一个实参是第二个实参中任意一个类对象或其子类的实例对象,那么返回True

In [15]: isinstance(D(), (D, B, C))
Out[15]: True
In [16]: isinstance(D(), (D, A, C))
Out[16]: True

type()与dir()

  • type()用于获得指定对象的类型
class MyClass(object):
    pass
mc = MyClass()

实例对象的类型是其对应的类对象

In [18]: type(mc)
Out[18]: __main__.MyClass
In [19]: type(18)
Out[19]: int
In [20]: type('abc')
Out[20]: str

类对象的类型是type,也就是说,类对象是type的一个实例对象

In [21]: type(MyClass)
Out[21]: type
In [22]: type(int)
Out[22]: type
In [23]: type(str)
Out[23]: type

自定义函数对象的类型是function

def do_sth():
    pass
In [26]: type(do_sth)
Out[26]: function

内置函数对象的类型是builtin_function_or_method

In [27]: type(dir)
Out[27]: builtin_function_or_method
In [28]: type(dir())
Out[28]: list

可以使用运算符==判断某个对象的类型是否是制定的类型

In [29]: type(18) == int
Out[29]: True
In [30]: type('abc') == str
Out[30]: True

对于基本数据类型,可以直接使用其对应的类名;如果不是基本数据类型,需要使用标准库中的模块types中定义的变量

In [37]: import types
In [38]: type(do_sth) == types.FunctionType
Out[38]: True
In [39]: type(print) == types.BuiltinFunctionType
Out[39]: True
  • dir()可获得其所有可以访问的属性和方法的列表(包括从父类中继承的属性和方法)
class MyClass(object):
    ca = "ca"
    
    def __init__(self):
        self.ia = "ia"
        
    def im(self):
        pass
    
    @classmethod
    def cm(cls):
        pass
    
    @staticmethod
    def sm():
        pass

类对象与实例对象的结果是有区别的,类对象中不包括实例属性

In [43]: print(dir(MyClass))
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', 
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', 
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', 
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', 
'__repr__', '__setattr__', '__sizeof__', '__str__', 
'__subclasshook__', '__weakref__', 'ca', 'cm', 'im', 'sm']
In [44]: print(dir(MyClass()))
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', 
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', 
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', 
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', 
'__repr__', '__setattr__', '__sizeof__', '__str__', 
'__subclasshook__', '__weakref__', 'ca', 'cm', 'ia', 'im', 'sm']

属性之增删改查

class MyClass(object):
    def __init__(self):
        self.x = 1
    
    def do_sth(self):
        print("do_sth被调用")
mc = MyClass()
  • hasattr(object, name)
    判断指定的对象object是否有参数name指定的属性或方法
In [46]: hasattr(mc, 'x')
Out[46]: True
In [47]: hasattr(mc, 'do_sth')
Out[47]: True
In [48]: hasattr(mc, 'y')
Out[48]: False
  • getattr(object, name[, default])
    获取指定的对象object中名为name的属性或方法。当object中不存在名为name的属性或方法如果不指定default,则抛出AttributeError;如果指定default,则返回default。如果可以直接写object.name就不要写getattr(object, ‘name’)
    getattr(object, name) 等价于 object.name=value
In [49]: getattr(mc, 'x')
Out[49]: 1
In [50]: getattr(mc, 'y', '查找的属性或方法不存在')
Out[50]: '查找的属性或方法不存在'
In [51]: f = getattr(mc, 'do_sth')
    ...: f()
do_sth被调用
  • setattr(object, ame, value)
    在指定的对象object中添加或修改名为参数name的属性或方法,添加或修改后的值为value
    setattr(object, name, value)等价于object.name=value
In [65]: setattr(mc, 'z', 3) #等价于mc.z = 3
    ...: getattr(mc, 'z')
Out[65]: 3
  • delattr(object, name)
    删除指定的对象object中名为参数name的属性或方法
    delattr(object, name)等价于del object.name
In [66]: delattr(mc, 'z')
    ...: hasattr(mc, 'z')
Out[66]: False

算数运算符重载

标准算数运算符在默认情况下不能用于自定义类对象的实例对象

In [69]: class MyClass1(object):
    ...:     pass
    ...: class MyClass2(object):
    ...:     pass
    ...: print(MyClass1() + MyClass2())
Traceback (most recent call last):

  File "<ipython-input-69-031bba855100>", line 7, in <module>
    print(MyClass1() + MyClass2())

TypeError: unsupported operand type(s) for +: 
			'MyClass1' and 'MyClass2'

如果想让标准算术运算符可以用于自定义类对象的实例对象,必须自定义类对象中实现标准算术运算符对应的一下特殊方法:
1、+对应的特殊方法是__add__()与__radd__()
2、-对应的特殊方法是__sub__()与__rsub__()
3、* 对应的特殊方法是__mul__()与__rmul__()
4、/对应的特殊方法是__truediv__()与__rtruediv__()
5、//对应的特殊方法是__floordiv__()与__rfloordiv__()

In [74]: print(list(dir(list)))
['__add__', '__class__', '__contains__', '__delattr__', 
'__delitem__', '__dir__', '__doc__', '__eq__', '__format__', 
'__ge__', '__getattribute__', '__getitem__', '__gt__', 
'__hash__', '__iadd__', '__imul__', '__init__', 
'__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', 
'__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', 
'__repr__', '__reversed__', '__rmul__', '__setattr__', 
'__setitem__', '__sizeof__', '__str__', '__subclasshook__', 
'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 
'pop', 'remove', 'reverse', 'sort']

假设两个运算数obj1和obj2,以+为例,对于obj1+obj2,需要在obj1对应的自定义类对象中实现特殊方法__add__(),或在obj2对应的自定义类对象中实现特殊方法__radd__()
在这里插入图片描述

In [75]: class MyClass1(object):
    ...:     def __add__(self, other):
    ...:         return "这是__add__+的结果"
    ...: 
    ...: class MyClass2(object):
    ...:     def __radd__(self, other):
    ...:         return "这是__radd__+的结果"
    ...: 
    ...: obj1 = MyClass1()
    ...: obj2 = MyClass2()
    ...: print(obj1 + obj2)
这是__add__+的结果
In [77]: class MyClass1(object):
    ...:    def __add__(self, other):
    ...:         print("特殊方法__add__被调用")
    ...:         return NotImplemented
    ...: 
    ...: class MyClass2(object):
    ...:     def __radd__(self, other):
    ...:         return "这是__radd__+的结果"
    ...: 
    ...: obj1 = MyClass1()
    ...: obj2 = MyClass2()
    ...: print(obj1 + obj2)
特殊方法__add__被调用
这是__radd__+的结果

__str__()与__repr__()

类对象的特殊方法__str__()和__repr__()用于自定义并返回实例对象的字符串表示形式

####第一系列####
In [78]: class MyClass(object):
    ...:     pass
    ...: 
    ...: mc = MyClass()
    ...: mc
Out[78]: <__main__.MyClass at 0x1f6cac27a58>
In [79]: print(mc)
<__main__.MyClass object at 0x000001F6CAC27A58>
In [80]: str(mc)
Out[80]: '<__main__.MyClass object at 0x000001F6CAC27A58>'
In [81]: repr(mc)
Out[81]: '<__main__.MyClass object at 0x000001F6CAC27A58>'
####第二系列####
In [82]: class MyClass(object):
    ...:     def __str__(self):
    ...:         return "__str__被调用"
    ...: 
    ...: mc = MyClass()
    ...: mc
Out[82]: <__main__.MyClass at 0x1f6cac2f128>
In [83]: print(mc)
__str__被调用
In [84]: str(mc)
Out[84]: '__str__被调用'
In [85]: repr(mc)
Out[85]: '<__main__.MyClass object at 0x000001F6CAC2F128>'
####第三系列####
In [86]: class MyClass(object):
    ...:     def __repr__(self):
    ...:         return "__repr__被调用"
    ...: 
    ...: mc = MyClass()
    ...: mc
Out[86]: __repr__被调用
In [87]: print(mc)
__repr__被调用
In [88]: str(mc)
Out[88]: '__repr__被调用'
In [89]: repr(mc)
Out[89]: '__repr__被调用'
####第四系列####
In [90]: class MyClass(object):
    ...:     def __str__(self):
    ...:         return "__str__被调用"
    ...:     def __repr__(self):
    ...:          return "__repr__被调用"
    ...: mc = MyClass()
    ...: mc
Out[90]: __repr__被调用
In [91]: print(mc)
__str__被调用
In [92]: str(mc)
Out[92]: '__str__被调用'
In [93]: repr(mc)
Out[93]: '__repr__被调用'

类对象的特殊方法之__str__()和__repr__()用于自定义并返回实例对象的字符串表示形式

  • 1、当在交互式命令行中直接打印一个实例对象时
    如果在实例对象对应的类中实现了特殊方法__repr__(),会自动调用该方法;
    否则会打印实例对象对应的类对象和实例对象在内存中的地址
  • 2、当调用内置函数打印一个实例对象时,
    如果在实例对象对应的类对象中实现了特殊方法__str__(),会自动调用该方法;
    否则,如果在实例对象对应的类对象中实现了特殊方法__repr__(),会自动调用该方法;
    否则会打印实例对象对应的类对象和实例对象在内存中的地址
  • 3、当调用内置函数str创建字符串并且实参是一个实例对象时,
    如果在实例对象对应的类对象中实现了特殊方法__str__(),在内置函数str的内部会自动调用该方法;
    否则,如果在实例对象对应的类对象中实现了特殊方法__repr__(),在内置函数str的内部会自动调用该方法;
    否则会打印实例对象对应的类对象和实例对象在内存中的地址
  • 4、当调用内置函数repr创建字符串并且实参是一个实例对象时,
    如果在实例对象对应的类对象中实现了特殊方法__repr__(),在内置函数repr的内部会自动调用该方法;
    否则会打印实例对象对应的类对象和实例对象在内存中的地址

通常情况下,类对象的特殊方法__str__()和__repr__()的实现代码是一样,因此,当实现了其中一个后,可以把其方法名赋值给另一个的方法名

class MyClass(object):
    def __str__(self):
        return "这是实例对象的字符串表示形式"
    
    __repr__ = __str__

内置函数str()和repr()都返回对象的字符串表示,其区别在于:
1、str()的返回值是给用户看的,更加用户友好
2、repr()的返回值是给程序开发者看的,是为调试服务的

In [95]: str("Hello,\nword!")
Out[95]: 'Hello,\nword!'
In [96]: repr("Hello,\nword!")
Out[96]: "'Hello,\\nword!'"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值