1.1.鸭子类型和多态
实现了__getitem__方法
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __getitem__(self, item):
return self.employee[item]
company = Company(["11", "22", "33"])
a = ['derek1','derek2']
name_set = set()
name_set.add('tom1')
name_set.add(('tom2'))
#extend里面可以添加任何可迭代的参数,
#给类添加一个魔法函数__getitem__,类就变成可迭代的
a.extend(company)
print(a) #['derek1', 'derek2', '11', '22', '33']
a.extend(name_set)
print(a) #['derek1', 'derek2', '11', '22', '33', 'tom2', 'tom1']
1.2.抽象基类(abc模块)待完善
抽象基类的作用类似于JAVA中的接口。在接口中定义各种方法,然后继承接口的各种类进行具体方法的实现。抽象基类就是定义各种方法而不做具体实现的类,任何继承自抽象基类的类必须实现这些方法,否则无法实例化
(1)判断类时候有某种属性
#判断类是否有某种属性
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __len__(self):
return len(self.employee)
com = Company(["11", "22", "33"])
#hasattr判断类有没有某种属性,方法也是类的属性
print(hasattr(com,"__len__")) #True
#虽然用hasattr可以判断,但正确的方式是定义一个抽象基类
#判定某个对象的类型,可以用抽象基类
from collections import Sized
print(isinstance(com,Sized)) #True 注释掉def __len__返回false
1.3.使用isinstance而不是type
类型即 (tuple,dict,int,float,list,bool等)
>>> isinstance(1,int)
True
>>>
>>> isinstance('1',str)
True
>>>
>>> isinstance(1,list)
False
(3)type()与isinstance()的区别:
- 共同点:都可以判断对象类型
- 不同点:对于一个 class 类的子类对象类型判断,type就不行了,而 isinstance 可以。
class A:
pass
class B(A):
pass
b = B()
#判断b是不是B的类型
print(isinstance(b,B)) #True
#isinstance内部会去检查继承链
print(isinstance(b,A)) #True
print(type(b) is B) #True
#b指向了B()对象,虽然A是B的父类,但是A是另外一个对象,它们的id是不相等的
print(type(b) is A) #False
1.4.类变量和实例变量
class A:
#类变量
bb = 11
def __init__(self,x,y):
#实例变量
self.x = x
self.y = y
a = A(2,3)
A.bb = 111111
print(a.x,a.y,a.bb) # 2 3 111111
print(A.bb) # 111111
a.bb = 2222 #实际上会在实例对象a里面新建一个属性bb
print(a.bb) # 2222
print(A.bb) # 111111
1.5.类和实例属性的查找顺序
class D(object):
pass
class C(D):
pass
class B(D):
pass
class A(B,C):
pass
#顺序:A,B,C,D
#__mro__,类的属性查找顺序(「方法解析顺序」(Method Resolution Order)
print(A.__mro__)
#(<class '__main__.A'>, <class '__main__.B'>,
# <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
class D(object):
pass
class E(object):
pass
class C(E):
pass
class B(D):
pass
class A(B,C):
pass
#顺序:A,B,D,C,E
print(A.__mro__)
1.6.类方法,静态方法,和实例方法
class Date():
#构造函数
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
#实例方法
def tomorrow(self):
self.day += 1
# 静态方法不用写self
@staticmethod
def parse_from_string(date_str):
year, month, day = tuple(date_str.split("-"))
# 静态方法不好的地方是采用硬编码,如果用类方法的话就不会了
return Date(int(year), int(month), int(day))
#类方法
@classmethod
def from_string(cls, date_str):
year, month, day = tuple(date_str.split("-"))
# cls:传进来的类,而不是像静态方法把类写死了
return cls(int(year), int(month), int(day))
def __str__(self):
return '%s/%s/%s'%(self.year,self.month,self.day)
if __name__ == "__main__":
new_day = Date(2018,5,9)
#实例方法
new_day.tomorrow()
print(new_day) #2018/5/10
#静态方法
date_str = '2018-05-09'
new_day = Date.parse_from_string(date_str)
print(new_day) #2018/5/9
# 类方法
date_str = '2018-05-09'
new_day = Date.from_string(date_str)
print(new_day) # 2018/5/9
1.7.python对象的自省机制
class Person:
'''人类'''
name = "user"
class Student(Person):
def __init__(self,school_name):
self.school_name = school_name
if __name__ == "__main__":
user = Student('仙剑')
#通过 __dict__ 查询有哪些属性
print(user.__dict__) #{'school_name': '仙剑'}
print(Person.__dict__) #{'__module__': '__main__', '__doc__': '人类', 'name': 'user',
'__dict__': <attribute '__dict__' of 'Person' objects>,
'__weakref__': <attribute '__weakref__' of 'Person' objects>}
print(Person.__doc__) #人类
#可以添加属性
user.__dict__['school_addr'] = '北京'
print(user.school_addr) #北京
#dir也可以查看属性,比__dict__功能更强大
print(dir(user))
#['__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_addr', 'school_name']
1.8.super函数
super执行的顺序
class A(object):
def __init__(self):
print('A')
class B(A):
def __init__(self):
print('B')
super(B, self).__init__()
class C(A):
def __init__(self):
print('C')
super(C, self).__init__()
class D(B,C):
def __init__(self):
print('D')
super(D, self).__init__()
if __name__ == '__main__':
print(D.__mro__)
#(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>,
#<class '__main__.A'>, <type 'object'>)
d = D() #D B C A
1.9.with语句(上下文管理器)
#上下文管理器
class Sample:
def __enter__(self):
print('enter')
#获取资源
return self
def __exit__(self, exc_type, exc_val, exc_tb):
#释放资源
print('exit')
def do_something(self):
print('doing something')
#会自动执行enter和exit方法
with Sample() as sample:
sample.do_something()
# 运行结果
enter
doing something
exit