Day1 PythonWeb全栈课程课堂内容
- 1. 深入类和对象
- 2. 魔法函数
- 3. 鸭子类型和多态
- 4. type和isinstance区别
- 5. 类属性和实例属性
- 6. super()函数
- 7. Python对象自省机制
1. 深入类和对象
Python中一切对象,Python中的函数和类也是对象
# Python中的函数和类也是对象,证明1:
def func(name='Sam'):
print(name)
if __name__ == '__main__':
my_func = func
my_func('Janice')
# isinstance()判断类型
print(isinstance(my_func, object)) # True 证明myfunc是一个对象
# Python中的函数和类也是对象,证明2:
def func(name='Sam'):
print(name)
class Func(object):
def __init__(self, name='Janice'):
print(name)
if __name__ == '__main__':
my_func = func
lsts = [] # 创建列表存储内容
lsts.append(my_func)
lsts.append(Func)
for lst in lsts:# 建立循环,打印列表内容
print(lst)
'''
<function func at 0x00000000003F2E18> # func的类型是function函数
<class '__main__.Func'> # Func的类型是class类
'''
for lst in lsts:
print(lst())
'''
Sam # 打印内容为func函数中print(name)的内容。
None # 函数内如果没有返回值得话,直接打印的就是空值None。
Janice # 打印内容为Func类中,方法__init__的print(name)中的内容。
<__main__.Func object at 0x0000000009FD5F28> # 返回一个类对象,类实例化。
'''
# 证明函数和类都是对象
# Python中的函数和类也是对象,证明3:中
def func_demo(name = 'Mike'):
print(name)
# 构成装饰器,创建闭包
def dec():
print('Start')
return func_demo
if __name__ == '__main__':
dec = dec()
dec('Sam')
'''
Start
Sam
'''
# dec = dec() 如同在文件中创建一个class类, 并且创建一个实例对象,例如:
class Demo:
def er(self, name = 'Janice'):
print('Start')
print('name')
if __name__ == '__main__':
dec = Demo('Sam')
dec
'''
Start
Sam
'''
- 注意点:
- 禁止使用中文名来命名文件名。
- 书写规范——来自菜鸟教程
2. 魔法函数
class Company(object):
def __init__(self, empl_list):
self.emplovee = empl_list
company = Company(['Sam', 'Janice', 'Mike'])
for em in company.emplovee:
print(em)
'''
Sam
Janice
Mike
'''
#----------------------------------------------------------------------------------
# 有了__getitem__的魔法函数,就不用输入company.emplovee,可以直接循环这个实例对象。例如:
class Company(object):
def __init__(self, empl_list):
self.emplovee = empl_list
def ___getitem__(self.item):
return self.emplovee[item]
company = Company(['Sam', 'Janice', 'Mike'])
for em in company:
print(em)
'''
Sam
Janice
Mike
'''
__repr__ , __str__
class Sam(object):
def __str__(self):
return "this is Sam __str__"
sam = Sam()
print(sam)
'''
this is Sam __str__
'''
- __str__ 魔法函数直接类的直接打印。把类变成一个字符串的形式。
class Sam(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "name: %s, age: %s"%(self.name, self.age)
sam = Sam('Sam', 26)
print(sam)
'''
name: Sam, age: 26
'''
# 如果不是用__str__魔法函数,我们则比较麻烦。需要调用类中的方法。
class Sam(object):
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
return "name: %s, age: %s"%(self.name, self.age)
sam = Sam('Sam', 26)
print(sam.speak())
'''
name: Sam, age: 26
'''
- __repr__ 和__str__ 所得功能相同。
class Sam(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return "name: %s, age: %s"%(self.name, self.age)
sam = Sam('Sam', 26)
print(sam)
'''
name: Sam, age: 26
'''
由此显示str比较易读,主要给用户看的。而repr主要给开发人员看的。
- 数学函数
3. 鸭子类型和多态
- 多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚"鸭子类型"
- 动态语言调用实例方法时不检查类型,只要方法存在,参数正确,就可以调用。这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
a = [1, 2]
b = [3, 4]
a.extend(b) # [1, 2, 3, 4]
print(b)
'''
def extend(self, iterable): # real signature unknown; restored from __doc__
""" L.extend(iterable) -> None -- extend list by appending elements from the iterable """
pass
''' # iterable 可迭代, 说明只要可迭代的就可使用extend
c = (3, 4)
d = {3, 4}
a.extend(c) # [1, 2, 3, 4]
a.extend(d) # [1, 2, 3, 4]
# 这就是鸭子类型
- 多态:定义时的类型和运行时的类型不一样,就称为多态。
class Dog(object):
def eat(self):
print("I want to eat dog's food")
class Cat(object):
def eat(self):
print("I want to eat cat's food")
class Fish(object):
def eat(self):
print("I want to eat fish's food")
alist = [Dog, Cat, Fish]
for animal in alist:
animal().eat()
'''
I want to eat dog's food
I want to eat cat's food
I want to eat fish's food
'''
4. type和isinstance区别
- type 不考虑 继承关系
- isinstance 考虑继承关系
a = 1
s = 'a'
print(isinstance(a, int)) # True
print(isinstance(s, str)) # True
class A:
pass
class B(A):
pass
b = B()
print(isinstance(b, B)) # True isinstance考虑继承关系
print(isinstance(b, A)) # True
# is 判断地址 == 判断数值上的相等
print(type(b) is B) # True type 不会考虑继承关系
print(type(b) is A) # False
5. 类属性和实例属性
- 基本查找顺序
class Case:
c = 3 # 类属性
def __init__(self, a, b):
self.a = a # 实例属性
self.b = b
case = Case(1, 2)
print(case.a, case.b, case.c) # 1, 2, 3
- 多继承查找顺序
- 实际上,python2.2(经典类)之前的算法:MRO算法,DFS(deep first search) 深度优先。
- 如下图,菱形继承,执行顺序如何?
- 在python2.2版本之后,引入BFS(广度优先)。
- 在python新式类,就引入了C3算法,通过className.mro来查看。
# 菱形例子
class D:
pass
class B(D):
pass
class C():
pass
class A(B, C):
pass
print(A.__mro__)
'''
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
'''
# U型例子
class D:
pass
class B(D):
pass
class E:
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'>)
'''
- 实例方法 类方法 静态方法
# 案例
class Date(object):
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tomorrow(self): # 加一日
self.day += 1
def __str__(self):
return "%s/%s/%s" % (self.year, self.month, self.day)
if __name__ == '__main__':
day = Date(2020, 12, 9)
day.tomorrow()
print(day)
'''
2020/12/10
'''
# ------------------------------
# 需求将 2020-12-9 转成 2020/12/10 输出
class Date(object):
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tomorrow(self): # 加一日
self.day += 1
def __str__(self):
return "%s/%s/%s" % (self.year, self.month, self.day)
if __name__ == '__main__':
date_str = '2020-12-9'
year, month, day = tuple(date_str.slipt('-'))
days = Date(int(year), int(month), int(day))
days.tomorrow()
print(days)
'''
2020/12/10
'''
---------------------------------------------------------
# 完善代码,将后面的需求进入方法中。
class Date(object):
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.slipt('-'))
return Date(int(year), int(month), int(day))
# 其中有Date 硬方法,不够完善, 如果Date类修改,则这个里面的Date也同样要修改
def __str__(self):
return "%s/%s/%s" % (self.year, self.month, self.day)
if __name__ == '__main__':
date_str = '2020-12-9'
days.parse_from_string(date_str)
print(days)
'''
2020/12/10
'''
------------------------------------------------
class Date(object):
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tomorrow(self): # 加一日
self.day += 1
@classmethod # 类方法
def parse_from_string(cls, date_str):
year, month, day = tuple(date_str.slipt('-'))
return cls(int(year), int(month), int(day))
def __str__(self):
return "%s/%s/%s" % (self.year, self.month, self.day)
if __name__ == '__main__':
date_str = '2020-12-9'
days.parse_from_string(date_str)
print(days)
'''
2020/12/10
'''
6. super()函数
class A:
def __init__(self, name, age):
self.name = name
self.age = age
class B(A):
def __init__(self, name, age, weight):
# super调用父类中的属性,不用重复输入
super().__init__(name, age)
self.weight = weight
if __name__ == '__main__':
b = B('Sam', 26, 66)
- super()继承
class A(object):
def __init__(self):
print("A")
class C(A):
def __init__(self):
print("B")
super().__init__()
class B(A):
def __init__(self):
print("C")
super().__init__()
class D(B,C):
def __init__(self):
print("D")
super().__init__()
# D->C->A->B->A ×
if __name__ == '__main__':
d = D()
'''
D
C
B
A
'''
print(d.__mro__)
'''
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
'''
7. Python对象自省机制
- 自省是通过一定的机制查询到对象的内部结构
- Python中比较常见的自省(introspection)机制(函数用法)有: dir(),type(), hasattr(), isinstance(),通过这些函数,我们能够在程序运行时得知对象的类型,判断对象是否存在某个属性,访问对象的属性
class Person():
name = 'Sam'
class Student(Person):
def __init__(self, school_name):
self.school_name = school_name
if __name__ == '__main__':
s = Student('Ningda')
print(s.__dict__) # {'school_name': 'Ningda'} 查看类内部的属性,但不能查看父类的属性。
s.__dict__['addres'] = 'Zhejiang'
print(s.addres) # Zhejiang 打印内容
print(dir(s))
'''
['__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__', 'addres', 'name', 'school_name']
'''
print(hasattr(Student, 'school_name')) # False
print(hasattr(s, 'school_name')) # True