python 中级用法
Prerequisite
老是用那几个 crud,都忘了类啊,装饰器啥的怎么用,重新回来学学~
参考文章:廖雪峰
基础知识
*args 是非关键字参数,用于元组,**kw 是关键字参数,用于字典
同时使用 *args 和 **kwargs 时,必须 *args 参数列要在 **kwargs 前(比如 foo(a=1, b='2', c=3, a', 1, None, )
会报错)
def foo(*args, **kwargs):
print('args = ', args)
print('kwargs = ', kwargs)
print('---------------------------------------')
if __name__ == '__main__':
foo(1, 2, 3, 4)
foo(a=1, b=2, c=3)
foo(1, 2, 3, 4, a=1, b=2, c=3)
foo('a', 1, None, a=1, b='2', c=3)
'''
args = (1, 2, 3, 4)
kwargs = {}
---------------------------------------
args = ()
kwargs = {'a': 1, 'b': 2, 'c': 3}
---------------------------------------
args = (1, 2, 3, 4)
kwargs = {'a': 1, 'b': 2, 'c': 3}
---------------------------------------
args = ('a', 1, None)
kwargs = {'a': 1, 'b': '2', 'c': 3}
---------------------------------------
'''
关键字参数
import os
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--theme', default='校园爱情', type=str, help='主题')
parser.add_argument('--file', default='./input/', type=str, help='文件地址')
args = parser.parse_args()
if not os.path.exists(args.file):
print('Cannot find input path: {0}'.format(args.file))
exit()
print(args.theme, args.file)
'''
python test.py --theme "happy" --file "./input/"
---------------------------------------
happy ./input/
'''
sys
这种方法可以引用上层文件
import sys
sys.path.append("..") # 或者 sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
subprocess
import subprocess
def runcmd(command):
# 不显示输入内容 stdout=subprocess.PIPE, stderr=subprocess.PIPE
# 编码方式 encoding="utf-8"
ret = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if ret.returncode == 0:
return("success:", ret)
else:
return("error:", ret)
runcmd(["python", "--version"])
super()._init_()
针对子类的,用于自动初始化,减少代码数的语句
参考博客:理解super()._init_()
class Car(object):
def __init__(self, owner, year, model):
self.owner = owner
self.year = year
self.model = model
class ElectricalCar(Car):
def __init__(self, battery, *args, **kwargs):
# 将剩下的参数打包送给 super
super().__init__(*args, **kwargs)
# 从参数列表中拿出 battery 初始化子类属性
self.battery = battery
def get_power(self):
"""打印电池信息"""
print(f'The battery of this car is {self.battery}')
car = ElectricalCar('10000kwh','Jarry', 2021, 'Model S')
car.get_power()
print(car.owner, car.year, car.model)
"""
The battery of this car is 10000kwh
Jarry 2021 Model S
"""
判断 变量/函数 类型
# 一般用 type 就行了
type(123)
# <class 'int'>
type(abs)
# <class 'builtin_function_or_method'>
type(a)
# <class '__main__.Animal'>
type(fn)==types.FunctionType
# True
type(abs)==types.BuiltinFunctionType
# True
type(lambda x: x)==types.LambdaType
# True
type((x for x in range(10)))==types.GeneratorType
# True
# 类就用 isinstance
# 实际上 type 能用的 isinstance 都能用,建议优先使用 isinstance 判断类型
# object -> Animal -> Dog -> Husky
isinstance(h, Dog)
# True
执行字符串
expr = """
a, b = ["123", "456"]
print(a, b)
"""
exec(expr)
# 123 456
直接赋值、浅拷贝和深度拷贝
列表和元组的浅拷贝(copy),可以分出两个独立的对象
字典的赋值和浅拷贝(copy)没区别,只有深拷贝可以分出两个独立的对象
# 赋值,相当于别名
# 字典浅拷贝
a = {1: [1,2,3]}
b = a.copy()
print(a, b)
# ({1: [1, 2, 3]}, {1: [1, 2, 3]})
a[1].append(4)
print(a, b)
# ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
# 字典深拷贝
import copy
c = copy.deepcopy(a)
print(a, c)
# ({1: [1, 2, 3, 4]}, {1: [1, 2, 3, 4]})
a[1].append(5)
print(a, c)
# ({1: [1, 2, 3, 4, 5]}, {1: [1, 2, 3, 4]})
创建二维数组
# 1. 直接创建法
test = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
# 2. 列表生成式法
test = [[0 for i in range(m)] for j in range(n)]
# 3. numpy 创建
import numpy as np
test = np.zeros((m, n), dtype=np.int)
高级特性
生成器 generator
简单介绍
# 普通列表
L = [x * x for x in range(10)]
print(L)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 生成器
g = (x * x for x in range(10))
print(next(g))
# 0
print(next(g))
# 1
print(next(g))
# 4
for n in g:
print(n)
'''
9
16
25
36
49
64
81
'''
斐波那契的运用
# 最普通的斐波那契
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
# 使用了生成器的斐波那契(print 变成了 yield)
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
# 正常的输出,最后不会输出 done
for n in fib(6):
print(n)
# 最后会输出 done
g = fib(6)
while True:
try:
x = next(g)
print('g:', x)
except StopIteration as e:
print('Generator return value:', e.value)
break
迭代器
可迭代对象:Iterable
迭代器:Iterator
凡是可作用于 for 循环的对象都是 Iterable 类型
凡是可作用于 next() 函数的对象都是 Iterator 类型,它们表示一个惰性计算的序列
# 集合数据类型如 list、dict、str 等是 Iterable 但不是 Iterator,不过可以通过 iter() 函数获得一个 Iterator 对象
# Python 的 for 循环本质上就是通过不断调用 next() 函数实现的,例如:
for x in [1, 2, 3, 4, 5]:
pass
# 完全等价于
# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
try:
# 获得下一个值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循环
break
函数式编程
匿名函数 lambda
直接举例
def is_odd(n):
return n % 2 == 1
L = list(filter(is_odd, range(1, 20)))
# 完全等价于
L = list(filter(lambda n:n%2 == 1 , range(1,20)))
装饰器
一句话,装饰器就是给原函数添加额外的功能(迭代原函数)的东西
装饰器的英文是 decorator,装饰器分为传参和非传参,下面写了两个模板
from datetime import datetime
import functools
# 一个普通的函数
def now():
print(datetime.now())
# 运行函数和打印函数的名字
now()
# 2022-07-26 17:55:02.891440
print(now.__name__)
# now
# 普通的装饰器(两层)
# @functools.wraps(func) 的功能相当于 wrapper.__name__ = func.__name__
# 使用 *args, **kw 的目的是完全接收 func 原本的传参
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@decorator
def now():
print(datetime.now())
now()
# call now():
# 2022-07-26 17:58:56.143251
print(now.__name__)
# now
# 使用参数的装饰器(三层)
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log('text')
def now():
print(datetime.now())
now()
# text now():
# 2022-07-26 17:59:50.026713
print(now.__name__)
# now
偏函数
偏函数可以简化参数操作
当函数的某个参数是我们可以提前获知的,那我们就可以将它固定住!
import functools
# 定义一个取余函数,默认和2取余;
def mod(x,y=2):
# 返回 True 或 False
return x % y == 0
# 假设我们要计算和3取余,如果不使用partial()函数,那么我们每次调用mod()函数时,都要写y=3
mod(4,y=3)
mod(6,y=3)
# 使用partial()函数
mod_3 = functools.partial(mod,y=3)
mod_3(4)
mod_3(6)
喜欢划水摸鱼的废人