再梳理一遍 Python 系列知识点,夯实基础,无他,唯手熟尔
Python 系列总结都是我自己平时的学习笔记,如果有不正确的地方,希望各位佬儿哥指正纠偏
print(0.1+0.2)
----------------------
0.30000000000000004
可以使用 decimal 模块解决浮点数精度问题:
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2'))
print(type(Decimal('0.1') + Decimal('0.2')))
print(type(Decimal('0.1')))
---------------------------------------------------------
0.3
<class 'decimal.Decimal'>
<class 'decimal.Decimal'>
注意:在使用 Decimal 时要用字符串来表示数字
def sum_even(numbers: list[int]):
"""
返回numbers中偶数的个数
:param numbers: 整数列表
"""
return sum(i % 2 == 0 for i in numbers)
s = 'TomAndMarry'
s2 = s.partition('And')
print(s2)
--------------------------------
('Tom ', 'And', ' Marry')
s = '明明是中文,却使用了英文标点.'
table = s.maketrans(',.', ',。')
s2 = s.translate(table)
print(s2)
-----------------------------------------------
明明是中文,却使用了英文标点。
# 用户每日奖励积分数量
DAILY_POINTS_REWARDS = 100
# VIP用户额外奖励20
VIP_EXTRA_POINTS = 20
from enum import Enum
class UserType(int, Enum):
# VIP用户
VIP = 3
# 小黑屋用户
BANNED = 13
def add_daily_points(user):
"""用户每天第一次登录增加积分"""
if user.type == UserType.BANNED:
return
if user.type == UserType.VIP:
user.points += DAILY_POINTS_REWARDS + VIP_EXTRA_POINTS
return
user.points += DAILY_POINTS_REWARDS
return
fruits = {'apple','orange','pineapple'}
def batch(item):
for _ in item:
yield _
print(next(batch(fruits)))
print(next(batch(fruits)))
print(next(batch(fruits)))
---------------------------------------
apple
apple
apple
因为每次调用生成器函数都会生成一个新的生成器对象,所以以上程序运行结果会输出三个 apple
fruits = {'apple','orange','pineapple'}
def batch(item):
for _ in item:
yield _
g = batch(fruits)
print(next(g))
print(next(g))
print(next(g))
-------------------------------------------------
pineapple
apple
orange
以上代码再次验证了'每次调用生成器函数都会生成一个新的生成器对象'结论
def batch_process(item):
result = []
for i in item:
# process_item = ..处理item
result.append(process_item)
return result
# 以上方法会有一个问题,当item过大时,会导致函数执行很耗时,并且若调用方想在某个process_item达到条件时中断,以上方法也是做不到的。所以可以使用生成器函数替代。
def batch_process_2(item):
for i in item:
# process_item = ..处理item
yield process_item
# 调用方
for processed_item in batch_process_2(items):
# 如果某个处理对象过期了,就中断当前的所有处理
if processed_item.has_expired():
break
类方法
1.用 def 在类里定义一个函数时,这个函数通常被称作方法。调用这个方法需要先创建一个类实例;
2.可以使用@classmethod装饰器定义类方法,它属于类,无需实例化也能调用;
3.作为一种特殊方法,类方法最常见的使用场景,就是定义工厂方法来生成新实例,类方法的主角是类型本身,当发现某个行为不属于实例,而是属于整个类型是,可以考虑使用类方法;
静态方法
1.如果发现某个方法不需要使用当前实例里的任何内容,那可以使用@staticmethod来定义一个静态方法;
2.和普通方法相比,静态方法不需要访问实例的任何状态,是一种与状态无关的方法,因此静态方法其实可以写成脱离于类的外部普通函数;
2.1.如果静态方法特别通用,与类关系不大,那么把他改成普通函数会更好;
2.2.如果静态方法与类关系密切,那么用静态方法更好;
2.3.相比函数,静态方法有一些先天优势,比如能被子类继承和重写;
属性装饰器
1.@property 装饰器模糊了属性和方法间的界限,使用它,可以把方法通过属性的方式暴露出来;
2.@property 除了可以定义属性的读取逻辑外,还支持自定义写入和删除逻辑;
class FilePath:
@property
def basename(self):
....
@property.setter
def basename(self, name):
....
@property.deleter
def basename(self):
....
经过@property的装饰以后,basename 已经从一个普通的方法变成了 property 对象,所以可以使用 basename.setter 和 basename.deleter 方法;
定义 setter 方法,该方法会在对属性赋值是被调用;
定义 deleter 方法,该方法会在删除属性时被调用;
isinstance() 函数
利用 isinstance() 函数,我们可以判断对象是否属于特定类型;
isinstance() 函数能理解类之间的继承关系,因此子类的实例同样可以通过基类的校验;
校验对象是否是 Iterable 类型
在 collections.abc 模块中,有许多和容器相关的抽象类,比如代表集合的 Set、代表序列的 Sequence 等,其中有一个最简单的抽象类:Iterable,他表示的是可迭代类型;
鸭子类型和抽象类总结
鸭子类型是一种编码风格,在这种风格下,代码只关心对象的行为,不关心对象的类型;
鸭子类型降低了类型校验的成本,让代码变得更灵活;
传统的鸭子类型里,各种对象接口和协议都是隐式的,没有统一的显示标准;
传统的 isinstance() 类型检查和鸭子类型的理念是相违背的;
抽象类是一种特殊的类,他可以通过钩子方法来定制动态的子类检查行为;
因为抽象类的定制子类化特征,isinstance() 也变得更灵活、更契合鸭子类型了;
使用@abstractmethod装饰器,抽象类可以强制要求子类在继承时重写特定方法;
除了抽象方法外,抽象类也可以实现普通的基础方法,供子类继承使用;
在 collections.abc 模块中,有许多与容器相关的抽象类;
对于 Python 入门及进阶,我推荐两本我认为值得多次阅读的书籍:
《Python 编程从入门到实践(第二版)》- 第一部分为基础语法部分,建议刚接触 Python 的同学多次阅读并实践,夯实基础利器!
《Python 工匠》- 整本无尿点,强烈建议多次阅读并实践,是 Python 进阶的不二之选!