Python技巧笔记

Python技巧总结

  1. 正确使用True和False的判断
false_value = [
    [],
    {},
    False,
    '',
    0,
    0.0,
    None,
]


for x in false_value:
    print(True if value else False)

  1. 正确返回None值
    一个函数里面可能多个返回值都为True或False,这时候就要用is明确指定返回值,如None
  2. if条件优化
    • 直接判断——效率最低
    • in list 列表判断——效率最高,推荐
    • in set 集合——效率居中
  3. 字符串格式化技巧
    • 直接拼接
    • '{}'.format
    • '%s'%()
    • python3.6+, f'I'm {age}' 推荐
  4. Flat is better than nested
    • import this可以打印python之禅
    • nested 指的是if 嵌套、一层层包裹,不推荐
    • flat要代码扁平化,用if、 elif,避免多个if,不满足条件直接返回,推荐
  5. 列表解析,也就是列表推导式
    除了减少代码量之外,还能提高运行效率,时间接近原来的一半
    示例:
[item for item in items if item%2 == 0]
  1. 字典解析
    示例:
a = [1, 2, 3, 4, 5, 6]
{item:str(item) for item in a}
  1. 字典合并
  • 循环添加,也可以字典解析,但并不推荐
  • update更新,d1.update(d2)
  • python3.5+, {**d1, **d2, **d3} 推荐
  1. 字典安全访问
  • try-except抛出异常
    # 默认空返回None,也可以设置
    d.get('name','unkown')
  • python内置defaultdict
from collection import defaultdict
d_new = defaultdict(lamda:'missing', d)
d_new['name'] # 返回name对应的
d_new['asdf'] # 不存在则返回missing
  1. 关于for循环,类中实现for循环
  • 示例
class A:
    def __init__(self):
        self.data = []
    def add(self, x):
        self.data.append(x)

    def __iter__(self):
        # return self.data.__iter__()
        # 这里也可以加一个for循环
        for item in self.data:
            yield item

class B():
    def __init__(self, x, y):
        self.x = x
        self.y = y

b1 = B(x=1, y=2)
b2 = B(x=3, y=4)

a = A()
a.add(b1)
a.add(b2)

for item in a:
    print(item.x, item.y)
  1. 为什么要使用yield
    一次性读取可能会占用太多内存,yield可以提高效率
  2. 如何在递归调用中使用yield
    示例:
import os
path = ''
def get_file(folder_name):
    for item in os.listdir(folder_name):
        full_path = os.path.join(folder_name, item)
        if os.path.isfile(full_path):
            yield full_path
        elif os.path.isdir(full_path):
            # 方法一
            for item in get_file(full_path):
                yield item
            # 方法二,python3
            yield from get_file(full_path)
for file_name in get_file(path):
    print(file_name)
  1. 巧用lambda
    函数参数为函数时,可以考虑能否用lambda实现
    Jupyter shift+tab可以查看信息,比如sort排序传入key
  2. 处理程序中的异常
    try-except,可以具体抛出某些异常。
    总的如except Exception as e:
    具体的如except DNSError:
  3. 函数默认参数
    为函数参数设置默认值
  4. 可变数量参数
def function(x, *args):
    print(args)

function(1,2,3,4)
# 结果
[2, 3, 4]

# 注意: 使用```*args```之后,x就不能赋值了,否则会报错SyntaxError
# 当如下形式时,x必须赋值,否则会报错TypeError:

def function(*args, x):
    print(args, x)

function(1,2,x=3)
  1. 字典和**kwargs的关系
    实现可变数量位置参数
def function(x, **kwargs):
    print(x, kwargs)

function(x=1, a=2, b=3, c=4)

# 运行结果
1 {'a':2, 'b':3, 'c':4}

def sum1(x, y):
    print(x+y)

sum(x=1, y=2)

sum(**{'x':1, 'y':'2'})
传入参数```**{'x':1, 'y':2}```与传入参数```x=1, y=2```返回结果一样
  1. 默认参数陷阱
    不建议用列表作为参数
def bad_default_arg(s, time, target=[]):
    for _ in range(time):
        target.append(a)
    return target

bad_default_arg(s='a', time=3) # 返回 ['a', 'a', 'a']
bad_default_arg(s='b', time=3, target='a') # 返回 ['a', 'b', 'b', 'b']
bad_default_arg(s='AB', time=2) # 返回 ['a', 'a', 'a', 'AB', 'AB']
# 使用列表作为参数时,假如不指定,则会使用上一次的默认值
bad_default_arg(s='F', time=2) # 返回 ['a', 'a', 'a', 'AB', 'AB', 'F', 'F']

解决方法:

def good_default_arg(s, time, target=None):
    if target is None:
        target = []
    for _ in range(time):
        target.append(a)
    return target
  1. 尽量避免使用from xxx import *
    库中方法可能与已命名方法重名,建议用什么引入什么
  2. 合理使用virtualenv与pip
    • 进入文件,virtualenv --python3.6 env 创建虚拟环境
    • 激活环境, source env/bin/activate
    • 安装使用的库
    • pip freeze,把已安装的库写入txt文件里
    • 退出环境, deactivate
    • pip install -r xxx.txt 安装所有的依赖
  3. 类的属性和实例属性
    • class类中定义属性,尽量在init下定义
    • 或者在class下定义
  4. 类实例的受保护属性和私有属性
    • 加一个下划线_,仍然可以被访问,即受保护
    • 加两个下划线,无法被访问,即私有,但是实际上还是可以访问的,只不过名字编程了类名_属性名
class A(object):
    """docstring for A"""
    def __init__(self, name, age):
        super(A, self).__init__()
        self.__name = name
        self.__age = age 

a = A(name='python', age=27)

a.__age  # 无法被访问
        
  1. 使用类的property
    访问类的属性,需要property,但是是只读的
    要修改的话,可以定义setter
class B:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def name(self):
        return self._name
    
    @property
    def age(self):
        return self._age
    
    @age.setter
    def age(self, value):
        self.__age = value

    def __str__(self):
        print('My name is {} and my age is {}'.format(self.__name, self.__age))

b = B('Demo', 30)
print(b)

b.age = 40 # 可以修改
  1. tuple元组技巧
    • 同时赋值,保证个数一致
    • enumerate(),将列表变为元组
a = [1, 2, 3, 4]
for item in enumerate(a):
    print(item)

# 返回
(0,1)
(1,2)
(2,3)
(3,4)
  1. 特殊元组namedtuple
import collections
Student = collections.namedtuple('Student', 'id, name, score')
students = [
    Student(1, 'ABC', 90),
    Student(2, 'XYZ', 85),
    Student(3, 'asdf', 80)
]

# 调用
for s in students:
    print('name={}, id={}, score={}'.format(s.name, s.id, s.score))

提高可读性及可维护性,效率并无太大区别

  1. dict和zip
    创建字典
# 1
dict(a=1,b=2)

# 2
data = (('a':1), ('b':2)) # 只要是可迭代对象都行
dict(data)

# 3
# 两个元素数量相同的列表
dict(zip(x,y))  # 生成对应字典
  1. 字典按照key/value大小排序
    dict(sorted(d.items(), key=lambda x:x[1], reverse=True))
  2. 通过debug学习Python生成器
    yield生成器
  3. string操作技巧
s = ' Last Checkpoint: a few seconds ago (unsaved changes) '
最好是链条式做完,而不是一个一个做
  1. 列表解析取代map和filter
  2. 上下文管理
    with open
  3. 一个单独的下划线可以怎么用
    • for循环中,不使用i,可用_代替
    • 输入1+2返回3,实际上3就赋值给了_
    • 取用列表或元组的元素时,无关紧要的可用_代替
  4. __str__和__repr__区别
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return f'name={self.name}, age={self.age}'
    def __repr__(self):
        return f'name:{self.name}, age:{self.age}'

p = Person('Python', 27)
print(p)  # 先找__str__没有再找__repr__,都没有打印地址

p # 命令行中输入p,有__repr__才能返回值,否则返回地址
  1. 定义自己的exception
from exception import NameTooShort

def validate(name):
    if len(name) < 10:
        raise NameTooShort('Name is too short.')

try:
    validate('test')
except NameTooShort as e:
    print(e)

# exceprion.py 文件下
class NameTooShort(ValueError):
    pass
# 多个错误可以定义一个基类继承自Exception,其他错误都继承这个基类
  1. mypy做静态类型检查
def sum(x: int, y: int) -> int: # x、y都是int对象,函数返回int对象
    return x + y

if __name__ == '__main__':
    print(sum('1', '2')) # 并不会报错,用mypy会提示希望是int,但却是str类型

  1. 改进的namedtuple
# python3.6+
from typing import NmaedTuple

class Car(NmaedTuple):
    color: str
    mileage: float
    automatic: bool
    # 以上类型只是建议,不用对应的类型也不会报错,mypy会报错

car = Car('red', '100.01', False)
car.mileage = 100 # 会报错,因为不支持修改数据

  1. 用哪种数据结构存储数据
    • 为了简单用dict或tuple,字典数据得不到保护,元组数据顺序不能乱
    • class,灵活,但是普通class属性还是可以改变的,也可以添加属性
    • NamedTuple,定义子类,得到有效保护
  2. Python3.7+ Data Class
from dataclasses import dataclass

@dataclass
class NewPeple:
    name: str
    age: int
    # 仅仅是提示

p1 = NewPeple('A', 20)
p2 = NewPeple('A', 20)

print(p1, p2) # 普通类还要重写__str__ ,__repr__
print('p1=p2?', p1==p2) # 普通类需要重写__eq__
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354