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)
posted @ 2022-07-26 16:35  筱团  阅读(109)  评论(0编辑  收藏  举报