python面向对象编程--issubclass()与isinstance()、type()与dir()、算术运算符重载、__str__()与__repr__()

本文详细介绍了Python中的面向对象编程概念,包括issubclass()和isinstance()函数用于判断类和实例的关系,type()和dir()函数获取对象类型和属性,以及如何通过特殊方法重载算术运算符,同时阐述了str()和__repr__()在表示实例对象字符串形式时的作用。

issubclass()与isinstance()

内置函数issubclass()用于判断类对象与类对象之间的关系。
内置函数issubclass接收两个实参,第一个实参是类对象,第二个实参是类对象或由类对象组成的元组。
当第二个实参是类对象时,如果第一个实参是第二个实参的子类,那么返回True。
当第二个实参是类对象组成的元组时,如果第一个实参是第二个实参中任意一个类对象的子类,那么返回True。

class A(object):
	pass
class B(object):
	pass
class C(object):
	pass
class D(A):
	pass
print(issubclass(D, A))  #True
print(issubclass(D, B))  #False

print(issubclass(D, (B, A, C)))  #True
print(issubclass(D, (B, C)))  #True

print(issubclass(bool, int))  
print(issubclass(bool, str))  

print(issubclass(bool, (str, int, dict)))  #True
print(issubclass(bool, (str, list, dict)))  #False

内置函数isinstance()用于判断实例对象与类对象之间的关系。
内置函数isinstance接收两个实参,第一个实参是实例对象,第二个实参是类对象或由类对象组成的元组。
当第二个实参是类对象时,如果第一个实参是第二个实参的实例对象,或者第一个实参是第二个实参的子类的实例对象,那么返回True。
当第二个实参是类对象组成的元组时,如果第一个实参是第二个实参中任意一个类对象或其子类的实例对象,那么返回True。

class A(object):
	pass
class B(object):
	pass
class C(object):
	pass
class D(A):
	pass
print(isinstance(D(), D))  #True
print(isinstance(D(), A))  #True

print(issubclass(D(), (D, B, C)))  #True
print(issubclass(D(), (B, A, C)))  #True

type()与dir()

type()

内置函数type()用于获得指定对象的类型。
实例对象的类型是其对应的类对象。
类对象的type就是type

class MyClass(object):
	pass
mc = MyClass()
print(type(mc))  #<class '__main__.MyClass'>
print(type(18))  #<class 'int'>
print(type('abc')  #<class 'str'>
print(type(MyClass))  #<class 'type'>
print(type(int))  #<class 'type'>
print(type(str))  #<class 'type'>

自定义函数的对象类型是function。
内置函数的对象类型是builtin_function_or_method。

def do_sth():
	pass
print(type(do_sth))  #<class 'function'>
print(type(dir))  #<class 'builtin_function_or_method'>
print(type(dir()))  #<class 'list'>

可以选择运算符==判断某个对象的类型是否是指定的类型。
对于基本数据类型,可以直接使用其对应的类名;如果不是基本数据类型,需要使用标准库中的模块types中定义的变量。

print(type(18) == int)  #True
print(type('abc') == str)  #True
import types
print(type(do_sth) = types.FunctionType)  #True
print(type(print) = types.BuiltinFunctionType)  #True

dir()

对于指定的类对象或实例对象,可以调用内置函数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
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']

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']

调用内置函数dir()后的返回值中,很多属性和方法都是以双下划线__开头和结尾的,这些属性和方法中的绝大多数都继承自类object。

以双下划线__开头和结尾的属性被称为特殊属性
以双下划线__开头和结尾的方法被称为特殊方法。

特殊属性和特殊方法都是系统预定义的,我们自定义的属性和方法不要以双下划线开头和结尾。

print(dir(object))
#['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

属性之增删改查

1.hasattr(object, name)
用于判断指定的对象object是否有参数name指定的属性和方法。
2.getattr(object, name[, default])
用于获取指定的对象object中名为name的属性和方法。
如果不指定参数default,那么当object中不存在名为name的属性或方法时,抛出AttributeError。
如果指定了参数default,那么当object中不存在名为name的属性或方法时,就会返回default。
getattr(object, name)等价于:object.name。
3.setattr(object, name, value)
用于在指定的对象object中添加或修改名为参数的属性或方法,添加或修改后的值为value。
setattr(object, name, value)等价于:object.name = value
4.delattr(object, name)
用于删除指定的对象object中名为参数name的属性或方法。
delattr(object, name)等价于:del object.name
只有在不知道对象信息的情况下,才会去获取对象的信息。

class MyClass(object):
	def __init__(self):
		self.x = 1
	
	def do_sth(self):
		print("do_sth被调用了")

mc = MyClass()

print(hasattr(mc,'x'))   #True
print(hasattr(mc,'do_sth'))   #True
print(hasattr(mc,'y'))   #False

print(getattr(mc,'x'))   #1
print(getattr(mc,'y'))   #AttributeError: 'MyClass' object has no attribute 'y'

print(getattr(mc, 'y', 2))   #2

print(getattr(mc, 'y', '查找的属性或方法不存在'))   #查找的属性或方法不存在

f = getattr(mc, do_sth')
f()
#do_sth被调用
setattr(mc,'z',3)   #等价于 mc.z = 3
print(getattr(mc,'z'))   #3

delattr(mc, 'z')
print(hasattr(mc, 'z'))   #False

算术运算符重载

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

class MyClass1(object):
	pass

class MyClass2(object):
	pass

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__()
假设两个运算数obj1和obj2,以+为例,对于obj1 + obj2,需要在obj1对应的自定义类对象中实现特殊方法__add__(),或在obj2对应的自定义类对象中实现特殊方法__radd__()。(r是right的缩写)

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__+的结果
class MyClass1(object):
	pass
		
class MyClass2(object):
	def __radd__(self, other):
		return "这是__radd__+的结果" 

obj1 = MyClass1()
obj2 = MyClass2()

print(obj1 + obj2)
#这是__radd__+的结果
class MyClass1(object):
	pass
		
class MyClass2(object):
	pass 

obj1 = MyClass1()
obj2 = MyClass2()

print(obj1 + obj2)
#TypeError: unsupported operand type(s) for +: 'MyClass1' and 'MyClass2'
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__+的结果
class MyClass1(object):
	def __add__(self, other):
		print("特殊方法__add__被调用")
		return NotImplemented
	
class MyClass2(object):
	def __radd__(self, other):
		print("特殊方法__radd__被调用")
		return NotImplemented 

obj1 = MyClass1()
obj2 = MyClass2()

print(obj1 + obj2)
#特殊方法__add__被调用
#特殊方法__radd__被调用
#TypeError: unsupported operand type(s) for +: 'MyClass1' and 'MyClass2'

str()与__repr__()

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

#第一系列
class MyClass(object):
	pass

mc = MyClass()
mc
#<__main__.MyClass at 0x275ae04fa20>

print(mc)
#<__main__.MyClass object at 0x00000275AE04FA20>

str(mc)
#'<__main__.MyClass object at 0x00000275AE04FA20>'

repr(mc)
#'<__main__.MyClass object at 0x00000275AE04FA20>'
#第二系列
class MyClss(object):
    def __str__(self):
        return "__str__被调用"
    
mc = MyClass()
mc
#<__main__.MyClass at 0x275ae067940>

print(mc)
#__str__被调用

str(mc)
#'__str__被调用'

repr(mc)
# '<__main__.MyClass object at 0x00000275AE067940>'
#第三系列
class MyClss(object):
    def __repr__(self):
        return "__repr__被调用"
    
mc = MyClass()
mc
#__repr__被调用

print(mc)
#__repr__被调用

str(mc)
#'__repr__被调用'

repr(mc)
#'__repr__被调用'
#第四系列
class MyClss(object):
    def __str__(self):
        return "__str__被调用"

	def __repr__(self):
        return "__repr__被调用"
    
mc = MyClass()
mc
#__repr__被调用

print(mc)
#__str__被调用

str(mc)
#'__str__被调用'

repr(mc)
#'__repr__被调用'

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

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

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

str("Hello,\nworld")
#'Hello,\nworld'

repr("Hello,\nworld")
#"'Hello,\\nworld'"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值