社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
动态语言调用实例方法时不检查类型,只要方法存在,参数正确,就可以调用。这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
a = [1,2]
b = [3,4]
c = (5,7)
d = {7,8}
a.extend(b)
print(a)
for item in c:
print(item)
打印
[1, 2, 3, 4]
5
7
extend(self,iterable)
方法的源码是
def extend(self, *args, **kwargs): # real signature unknown
""" Extend list by appending elements from the iterable. """
pass
并没有实现具体的代码,底层是用C语言封装的。
iterable:
可迭代的对象,可以用for。
extend方法的参数是可迭代对象,所以列表、元组、集合都能作为extend方法的参数。
a = [1,2]
b = [3,4]
c = (5,7)
d = {7,8}
a.extend(c)
print(a)
b.extend(d)
print(b)
打印
[1, 2, 5, 7]
[3, 4, 8, 7]
多态:
定义时的类型和运行时的类型不一样,此时就成为多态。
class Cat(object):
def say(self):
print('I am a cat')
class Dog(object):
def say(self):
print('I am a dog')
class Duck(object):
def say(self):
print('I am a duck')
animal_list = [Cat, Dog, Duck]
for animal in animal_list:
animal().say()
打印
I am a cat
I am a dog
I am a duck
抽象基类(abstract base class,ABC):
抽象基类就是类里定义了纯虚成员函数的类。纯虚函数只提供了接口,并没有具体实现。
换句话说,抽象基类就是定义各种方法而不做具体实现的类,任何继承自抽象基类的类必须实现这些方法,否则无法实例化。
特点:
例如:Sized判断某个类是否实现了__len__()
方法。
from collections.abc import Sized
class Demo(object):
def __init__(self,name):
self.name = name
def __len__(self):
#魔法方法,加入才能使用len()方法
return len(self.name)
def test(self):
pass
d = Demo(['Tom','Jack'])
print(len(d))
#hasattr()方法用于判断对象是否具有某个方法
print(hasattr(d,'__len__'))
print(hasattr(d,'test'))
print(isinstance(d,Demo))
print(isinstance(d,Sized))
打印
2
True
True
True
强制子类必须实现某个方法:
class CacheBase(object):
def get(self, key):
pass
def set(self, key, value):
pass
class RedisBase(CacheBase):
pass
r = RedisBase()
r.get('Tom')
方法一:父类方法中抛出异常
class CacheBase(object):
def get(self,key):
# pass
raise ValueError
def set(self,key,value):
# pass
raise NotImplementedError
class RedisBase(CacheBase):
pass
r = RedisBase()
r.get('Tom')
运行会报错
Traceback (most recent call last):
File "xxx/demo.py", line 89, in <module>
r.get('Tom')
File "xxx/demo.py", line 79, in get
raise ValueError
ValueError
重写父类中的方法:
class CacheBase(object):
def get(self,key):
# pass
raise ValueError
def set(self,key,value):
# pass
raise NotImplementedError
class RedisBase(CacheBase):
# pass
#重写父类中的方法
def get(self,key):
pass
r = RedisBase()
r.get('Tom')
再次运行无报错。
方法二:父类继承抽象基类,方法加装饰器
父类继承抽象基类使子类必须继承父类指定的所有抽象方法。
import abc
class CacheBase(metaclass=abc.ABCMeta):
@abc.abstractmethod
def get(self,key):
pass
# raise ValueError
@abc.abstractmethod
def set(self,key,value):
pass
# raise NotImplementedError
class RedisBase(CacheBase):
#重写父类中的方法
def get(self,key):
pass
r = RedisBase()
r.get('Tom')
运行会报错
Traceback (most recent call last):
File "xxx/demo.py", line 94, in <module>
r = RedisBase()
TypeError: Can't instantiate abstract class RedisBase with abstract methods set
子类继承父类的所有方法后
import abc
class CacheBase(metaclass=abc.ABCMeta):
@abc.abstractmethod
def get(self,key):
pass
# raise ValueError
@abc.abstractmethod
def set(self,key,value):
pass
# raise NotImplementedError
class RedisBase(CacheBase):
#重写父类中的方法
def get(self,key):
pass
def set(self,key,value):
pass
r = RedisBase()
r.get('Tom')
再次运行不报错。
加了装饰器@abc.abstractmethod
的父类方法必须被子类继承重写。
i = 1
s = 'hello'
print(isinstance(i,int))
print(isinstance(s,int))
print(isinstance(s,str))
打印
True
False
True
isinstance()
方法会考虑类的继承关系。
class A(object):
pass
class B(A):
pass
b = B()
print(isinstance(b,B))
print(isinstance(b,A))
打印
True
True
type()
没有考虑类的继承关系。
class A(object):
pass
class B(A):
pass
b = B()
print(type(b) is B)
print(type(b) is A)
打印
True
False
类属性可以向上查找,实例属性不能向下查找。
class A:
#类属性
aa = 1
#实例方法
def __init__(self,x,y):
#实例属性
self.x = x
self.y = y
a = A(1,2)
print(a.x,a.y,a.aa)
try:
print(A.x)
except Exception as e:
print(e.args[0])
A.aa = 11
#相当于在实例化时增加self.aa = 22
a.aa = 22
print(a.aa)
print(A.aa)
b = A(1,2)
print(b.aa)
打印
1 2 1
type object 'A' has no attribute 'x'
22
11
11
class A(object):
name = 'Corley'
def __init__(self):
self.name = 'cl'
a =A()
print(a.name)
print(A.name)
打印
cl
Corley
DFS(deep first search):A->B->D->C->E
class D(object):
pass
class B(D):
pass
class E(object):
pass
class C(E):
pass
class A(B,C):
pass
print(A.__mro__)
打印
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class 'object'>)
顺序为A->B->D->C->E->object。
BFS:A->B->C->D
class D(object):
pass
class B(D):
pass
class C(D):
pass
class A(B,C):
pass
print(A.__mro__)
打印
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
顺序为A->B->C->D->object。
Python新式类继承的C3算法:https://www.cnblogs.com/blackmatrix/p/5644023.html。
自省是通过一定的机制查询到对象的内部结构。
Python中比较常见的自省(introspection)机制(函数用法)有:dir()
,type()
, hasattr()
, isinstance()
。
通过这些函数,我们能够在程序运行时得知对象的类型,判断对象是否存在某个属性,访问对象的属性。
class Person(object):
name = 'Corley'
class Student(Person):
def __init__(self,school_name):
self.school_name = school_name
user = Student('CUFE')
#__dict__不包括父类属性
print(user.__dict__)
print(user.name)
print(dir(user))
打印
{'school_name': 'CUFE'}
Corley
['__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__', 'name', 'school_name']
又如
a = [1,2]
try:
print(a.__dict__)
except Exception as e:
print(e.args[0])
print(dir(a))
print(list.__dict__)
打印
'list' object has no attribute '__dict__'
['__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']
{'__repr__': <slot wrapper '__repr__' of 'list' objects>, '__hash__': None, '__getattribute__': <slot wrapper '__getattribute__' of 'list' objects>, '__lt__': <slot wrapper '__lt__' of 'list' objects>, '__le__': <slot wrapper '__le__' of 'list' objects>, '__eq__': <slot wrapper '__eq__' of 'list' objects>, '__ne__': <slot wrapper '__ne__' of 'list' objects>, '__gt__': <slot wrapper '__gt__' of 'list' objects>, '__ge__': <slot wrapper '__ge__' of 'list' objects>, '__iter__': <slot wrapper '__iter__' of 'list' objects>, '__init__': <slot wrapper '__init__' of 'list' objects>, '__len__': <slot wrapper '__len__' of 'list' objects>, '__getitem__': <method '__getitem__' of 'list' objects>, '__setitem__': <slot wrapper '__setitem__' of 'list' objects>, '__delitem__': <slot wrapper '__delitem__' of 'list' objects>, '__add__': <slot wrapper '__add__' of 'list' objects>, '__mul__': <slot wrapper '__mul__' of 'list' objects>, '__rmul__': <slot wrapper '__rmul__' of 'list' objects>, '__contains__': <slot wrapper '__contains__' of 'list' objects>, '__iadd__': <slot wrapper '__iadd__' of 'list' objects>, '__imul__': <slot wrapper '__imul__' of 'list' objects>, '__new__': <built-in method __new__ of type object at 0x00007FFDDE682D30>, '__reversed__': <method '__reversed__' of 'list' objects>, '__sizeof__': <method '__sizeof__' of 'list' objects>, 'clear': <method 'clear' of 'list' objects>, 'copy': <method 'copy' of 'list' objects>, 'append': <method 'append' of 'list' objects>, 'insert': <method 'insert' of 'list' objects>, 'extend': <method 'extend' of 'list' objects>, 'pop': <method 'pop' of 'list' objects>, 'remove': <method 'remove' of 'list' objects>, 'index': <method 'index' of 'list' objects>, 'count': <method 'count' of 'list' objects>, 'reverse': <method 'reverse' of 'list' objects>, 'sort': <method 'sort' of 'list' objects>, '__doc__': 'Built-in mutable sequence.nnIf no argument is given, the constructor creates a new empty list.nThe argument must be an iterable if specified.'}
易知,列表没有__dict__
属性,列表对象有__dict__
。
在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法。
但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用
原文链接:https://blog.csdn.net/CUFEECR/article/details/104109365
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!