轻松玩转AI路径:
- 从Python开始 [链接]
- 数据科学 [链接]
- 机器学习 [链接]
- 深度学习——神经网络 [链接]
从Python开始
Python3高级编程和异步IO并发编程 目录:
一、python中一切皆对象
1.python中一切皆是对象
1)动态语言
2)函数和类也是对象,属于python的一等公民。
- 赋值给一个变量
- 可以添加到集合对象中
- 可以作为参数传递给函数
- 可以当做函数的返回值
# 赋值给一个变量
def ask(name='MJ'):
print(name)
my_func = ask
my_func('MJ') # 返回:MJ
class Person:
def __init__(self):
print('MJ1')
my_class = Person
my_class()
# 返回:MJ1
# 可以添加到集合对象中
# 可以作为参数传递给函数
obj_list = []
obj_list.append(ask)
obj_list.append(Person)
for item in obj_list:
print(item)
# 返回:
# MJ
# None
# MJ1
# <__main__.Person object at ...>
# 可以当做函数的返回值
def decorator_func():
print('dec start')
return ask
my_ask = decorator_func()
my_ask('tom')
# 返回:
# dec start
# tom
2. type、class和object的关系
a = 1
b = 'abc'
# type -> int/str -> 1
type(1) # <class 'int'>
type(int) # <class 'type'>
type(b) # <class 'str'>
type(str) # <class 'type'>
# type -> class -> object
class Student():
pass
stu = Student()
type(stu) # <class '__main__.Student'>
type(Student) # <class 'type'>
a = [1, 2]
type(a) # <class 'list'>
type(list) # <class 'type'>
# object 是最顶层基类
Student.__bases__ # <class 'object'> # 基类就是 object
class MyStudent(Student):
pass
Student.__bases__ # <class '__main__.Student'>
# type 也是一个类,同时也是一个对象
type.__bases__ # <class 'object'>
type(object) # <class 'type'>
object.__bases__ # ()
3. python中的常见内置类型
1)对象的三个特征:
- 身份 —— id()
- 类型 —— tpye()
- 值
2)None(None对象全局只有一个)
3)数值:
- int
- float
- complex
- bool
4)迭代类型
5)序列类型:
- list
- bytes、bytearray、memoryview (二进制序列)
- range
- tuple
- str
- array
6)映射(dict)
7)集合:
- set
- frozenset
8)上下文管理类型(with)
9)其他:
- 模块类型
- class和实例
- 函数类型
- 方法类型
- 代码类型
- object类型
- type类型
- ellipsis类型 (省略号)
- notimplemented类型
二、魔法函数
- 函数名以 双下划线开头和结尾 的函数。
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
company = Company(['tom', 'bob', 'jane'])
emploee = company.employee
for em in emploee:
print(em)
等同于:
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __getitem__(self, item):
return self.employee[item]
company = Company(['tom', 'bob', 'jane'])
for em in company:
print(em)
1. python的数据模型以及数据模型对python的影响
- 魔法函数并非继承object,而是独立存在的。
- 实现一个特定魔法函数之后,操作就会变得简单。
- 魔法函数会直接影响到python语法本身,会影响python的内置函数调用。
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __getitem__(self, item):
return self.employee[item]
company = Company(['tom', 'bob', 'jane'])
company1 = company[:2]
print(len(company))
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __len__(self):
return len(self.employee)
company = Company(['tom', 'bob', 'jane'])
print(len(company))
2. 魔法函数一览
1)非数学运算
(1)字符串表示:
__repr__
__str__
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __str__(self):
return ','.join(self.employee)
company = Company(['tom', 'bob', 'jane'])
company # 隐含调用 __repr__
# 返回:<__main__.Company at ...>
print(company) # 自动调用 __str__
# 返回:'tom','bob','jane'
(2)集合、序列相关:
__len__
__getitem__
__setitem__
__delitem__
__contains__
(3)迭代相关:
__iter__
__next__
(4)可调用:
__call__
(5)with 上下文管理器:
__enter__
__exit__
(6)数值转换:
__abs__
__bool__
__int__
__float__
__hash__
__index__
(7)元类相关:
__new__
__init__
(8)属性相关:
__getattr__、__setattr__
__getattribute__、__setattribute__
__dir__
(9)属性描述符:
__get__、__set__、__delete__
(10)协程:
__await__、__aiter__、__anext__、
__aenter__、__aexit__
2)数学运算
(1)一元运算符:
__neg__(-)、__pos__(+)、__abs__
(2)二元运算符:
__lt__ (<)、 __le__ (<=) 、
__eq__ (==) 、 __ne__ (!=) 、
__gt__ (>) 、 __ge__ (>=)
(3)算术运算符:
__add__ (+) 、 __sub__ (-) 、
__mul__ (*) 、 __truediv__ (/) 、
__floordiv__ (//) 、 __mod__ (%) 、
__divmod__ divmod() 、
__pow__ (**) 或 pow() 、 __round__ round()
(4)反向算术运算符:
__radd__ 、 __rsub__ 、 __rmul__ 、
__rtruediv__ 、 __rfloordiv__ 、
__rmod__ 、 __rdivmod__ 、 __rpow__
(5)增量赋值算术运算符:
__iadd__ 、 __isub__ 、 __imul__ 、
__itruediv__ 、 __ifloordiv__ 、
__imod__ 、 __ipow__
(6)位运算符:
__invert__ (~)、 __and__ (&) 、
__or__ (|) 、 __xor__ (^)、
__lshift__ (<<) 、 __rshift__ (>>)
(7)反向位运算符:
__rlshift__ 、 __rrshift__ 、
__rand__ 、 __rxor__ 、 __ror__
(8)增量赋值位运算符:
__ilshift__ 、 __irshift__ 、
__iand__ 、 __ixor__ 、 __ior__
三、深入类和对象
1. 鸭子类型和多态
- 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
- 所有的类或对象都实现了一个共同的方法,方法名要一样,这些类可以归为同一种类型,这样就可以同时调用这些类的方法。
# 鸭子类型
class Cat(object):
def say(self):
print('i an a cat')
class Dog(object):
def say(self):
print('i an a dog')
class Duck(object):
def say(self):
print('i an a duck')
# animal 可以赋值为 Cat、Dog、Duck,这就是多态。
animal_list = [Cat, Dog, Duck]
for animal in animal_list:
animal().say()
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __getitem__(self, item):
return self.employee[item]
company = Company(['tom', 'bob', 'jane'])
a = ['MJ1', 'MJ2']
b = ['MJ2', 'MJ1']
name_tuple = ('MJ3', 'MJ4')
name_set = set()
name_set.add('MJ5')
name_set.add('MJ6')
# extend 只要是可迭代类型即可
# 会调用 对象 里面的迭代器(隐式调用):__iter__ , __getitem__
a.extend(b) # 返回:['MJ1', 'MJ2', 'MJ2', 'MJ1']
#a.extend(name_tuple) # 返回:['MJ1', 'MJ2', 'MJ3', 'MJ4']
#a.extend(name_set) # 返回:['MJ1', 'MJ2', 'MJ5', 'MJ6']
#a.extend(company) # 返回:['MJ1', 'MJ2', 'tom', 'bob', 'jane']
print(a)
2. 抽象基类(abc模块)
- 抽象基类不能实例化。
# 检查某个类是否有某种方法
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __len__(self):
return len(self.employee)
com = Company(['MJ1', 'MJ2'])
print(len(com)) # 返回:2
# 可判断某类是否有某属性
print(hasattr(com, '__len__')) # 返回:True
# 可判断类是否有某种类型
# 我们在某些情况之下希望判定某个对象的类型
from collections.abc import Sized
isinstance(com, Sized) # 返回:True
# 我们需要强制某个子类必须实现某些方法
# 如:实现了一个web框架,集合cache(如希望可替换成 redis, cache, memorychache 之一)
# 则需要设计一个抽象基类,指定子类必须实现某些方法
# 如何去模拟一个抽象基类:
class CacheBase():
def get(self, key):
raise NotImplementedError
def set(set, key, value):
raise NotImplementedError
class RedisCache(CacheBase):
pass
redis_cache = RedisCache()
# 调用时会抛出异常
redis_cache.set('key', 'value')
# 如果我们希望初始化时就抛出异常:
import abc
class CacheBase(metaclss=abc.ABCMeta):
@abc.abstractmethod
def get(self, key)
pass
@abc.abstractmethod
def set(set, key, value):
raise NotImplementedError
class RedisCache(CacheBase):
pass
# 初始化时会抛出异常
redis_cache = RedisCache()
注:不建议使用抽象基类,建议使用 isinstance
3. isinstance和type的区别
- 使用 isinstance 而不是 type
class A:
pass
class B(A):
pass
b = B()
print(isinstance(b, B)) # 返回:True
print(isinstance(b, A)) # 返回:True
print(type(b)) # 返回:<class '__main__.B'>
print(type(b) is B) # 返回:True
# type 无法找出继承关系
print(type(b) is A) # 返回:False
4. 类变量和对象变量
class A:
aa = 1 # 类变量
def __init__(self, x, y): # self是类的实例
# self.x 和 self.y 的 x 和 y 属于 self(即对象变量的值),而不是类。
self.x = x
self.y = y
a = A(2, 3) # 实例就是对象。实例变量就是对象变量。
print(a.x, a.y, a.aa) # 返回:2 3 1
print(A.aa) # 返回:1
print(A.x, A.y) # 会抛出异常
A.aa = 11
print(a.x, a.y, a.aa) # 返回:2 3 11
print(A.aa) # 返回:11
a.aa = 11
print(a.x, a.y, a.aa) # 返回:2 3 100
print(A.aa) # 返回:11
5. 类属性和实例属性以及查找顺序
- 由下而上
- 属性查找顺序按 C3算法
class A:
name = 'A'
a = A()
print(a.name) # 返回:A
class A:
name = 'A'
def __init__(self):
self.name = 'obj'
a = A()
print(a.name) # 返回:obj
# 新式类,默认继承 object
class D:
pass
class C(D):
pass
class B(D):
pass
class A(B, C):
pass
# 查看查找顺序
print(A.__mro__)
# (<class '__main__.A'>,<class '__main__.B'>,<class '__main__.C'>,<class '__main__.D'>,<class '__main__.object'>)
# 新式类,默认继承 object
class D:
pass
class E:
pass
class C(E):
pass
class B(D):
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 '__main__.object'>)
6. 静态方法、类方法、对象方法以及参数
# 实例方法(self)
class Date:
# 构造函数
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 '{year}/{month}/{day}'.format(year=self.year, month=self.month, day=self.day)
if __name__ == '__main__':
new_day = Date(2018, 12, 31)
new_day.tomorrow() # python会自动转换 tomorrow(new_day) 调用
print(new_day) # 返回:2018/12/32
#2018-12-31
date_str = '2018-12-31'
year, month, day = tuple(date_str.split('-'))
new_day = Date(int(year), int(month), int(day))
print(new_day) # 返回:2018/12/31
使用静态方法优化:
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tomorrow(self):
self.day += 1
# 静态方法
@staticmethod
def parse_from_string(date_str):
year, month, day = tuple(date_str.split('-'))
return Date(int(year), int(month), int(day))
def __str__(self):
return '{year}/{month}/{day}'.format(year=self.year, month=self.month, day=self.day)
if __name__ == '__main__':
new_day = Date(2018, 12, 31)
new_day.tomorrow()
print(new_day) # 返回:2018/12/32
#2018-12-31
# 用 staticmethod 完成初始化
date_str = '2018-12-31'
new_day = Date.parse_from_string(date_str)
print(new_day) # 返回:2018/12/31
静态方法缺点:更改类名时需要更改静态方法返回对象
使用类方法优化:
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tomorrow(self):
self.day += 1
# 类方法
@classmethod
def from_string(cls, date_str) # cls 是类本身
year, month, day = tuple(date_str.split('-'))
return cls(int(year), int(month), int(day))
@staticmethod
def valid_str(date_str): # 判断日期是否合规
year, month, day = tuple(date_str.split('-'))
if int(year)>0 and (int(month)>0 and int(month<=12) and (int(day)>0 and int(day)<=31):
return True
return False
def __str__(self):
return '{
year}/{
month}/{
day}'.format(year=self.year, month=self.month, day=self.day)
if __name__ == '__main__':
new_day = Date(2018, 12, 31)
new_day.tomorrow()
print(new_day) # 返回:2018/12/32
#2018-12-31
# 用 classmethod 完成初始化
date_str = '2018-12-31'
new_day = Date.from_string(date_str)
print(new_day) # 返回:2018/12/31
print(Date.valid_str('2018-12-32')) # 返回:False
7. 数据封装和私有属性
import Date
class User:
def __init__(self, birthday):
# 双下滑线开头 __ 为私有属性
self.__birthday = birthday
def get_age(self):
return 2018 - self.__birthday.year
if __name__ == '__main__':
user = User(Date(1990,2,1))
print(user.get_age())
# 会报错,私有属性不允许类外部访问
print(user.__birthday)
# 非要访问,可使用:
print(user._User__birthday)
8. python对象的自省机制
- 自省是通过一定的机制查询到对象的内部结构
import Date # 上述 7 的内容
class Person:
name = 'user'
class Student(Person):
def __init__(self, school_name):
self.scool_name = school_name
if __name__ == '__main__':
user = Student('mooc')
# 通过 __dict__ 查询属性
print(user.__dict__) # 返回:{'scool_name':'mooc'}
print(user.name) # 返回:user
#print(Person.__dict__)
user.__dict__['school_addr'] = '北京市'
print(user.school_addr) # 返回:北京市
print(dir(user))
9. super函数
为什么要调用super?
from threading import Thread
class MyThread(Thread):
def __init__(self, name, user):
self.user = user
super().__init__(name=name) # 可使用多线程父类的name属性
super执行顺序不是调用父类,而是按MRO算法调用
class A:
def __init__(self):
print('A')
class B:
def __init__(self):
print('B')
super().__init__()
class C(A):
def __init__(self):
print('C')
super().__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'>,<class 'object'>)
d = D()
# 返回:
# D
# B
# C
# A
10. 对多继承mixin模式
- mixin模式特点:
- mixin类功能单一
- 不和基类关联,可以和任意基类组合,基类可以不和mixin关联就能初始化成功
- 在mixin不要使用super用法
11. 上下文管理器with语句
def exe_try():
try:
print('code started')
raise KeyError
return 1
except KeyError as e:
print('key error')
return 2
else:
print('other error')
return 3
finally:
print('finally')
return 4
if __name__ == '__main__':
result = exe.try()
print(result)
# finally 有 return 则直接返回,无则返回上一个的 return 2
# 返回:
# code started
# key error
# finally
# 4
# 上下文管理器协议
class Sample():
def __enter__(self):