海南的网站建设公司,在哪查找网站的建设者,贵州省建设厅网站造价工程信息,做的美食视频网站Python 提供丰富了内置函数#xff0c;这些函数的使用频率非常用#xff0c;在编程过程中熟练使用内置函数可以大大减少我们的代码逻辑和代码量。
Python 解释器内置了很多函数和类型#xff0c;任何时候都能使用。这些内置函数直接使用#xff0c;是不需要导入库的。
内…Python 提供丰富了内置函数这些函数的使用频率非常用在编程过程中熟练使用内置函数可以大大减少我们的代码逻辑和代码量。
Python 解释器内置了很多函数和类型任何时候都能使用。这些内置函数直接使用是不需要导入库的。
内置函数列表 - 函数 功能 A abs() 数字的绝对值 aiter() 异步迭代器 all() 是否全为 True any() 是否有 True 值 anext() 异步迭代下一项 ascii() 转为 ASCII 字符 B bin() 转为二进制字符串 bool() 返回布尔值 breakpoint() 设置断点 bytearray() 生成字节数组 bytes() 生成字节序列 C callable() 对象是否可调用 chr() Unicode 字符串 classmethod() 方法封装成类方法 compile() 编译为代码对象 complex() 创建复数 D delattr() 删除对象属性 dict() 创建字典 dir() 对象的所有属性和方法 divmod() 计算商和余数 E enumerate() 添加元素索引 eval() 执行字符串表达式 exec() 执行复杂代码 F filter() 元素过滤 float() 构造浮点数对象 format() 格式化 frozenset() 构建不可变集合 G getattr() 获取对象属性 globals() 全局变量 H hasattr() 检测对象属性 hash() 对象的哈希值 help() 内置帮助 hex() 16进制字符串 I id() 对象标识值 input() 获取输入字符串 int() 构造整数 isinstance() 实例类型检测 issubclass() 子类检测 iter() 生成迭代器 L len() 对象长度 list() 创建列表 locals() 当前本地符号表的字典 M map() 对序列元素应用函数处理 max() 最大元素 memoryview() 创建内存视图 min() 最小元素 N next() 迭代下一项 O object() 空对象 oct() 转为八进制字符串 open() 打开文件 ord() Unicode 码位编号 P pow() 求n次幂 print() 打印对象内容 property() 修饰方法 R range() 等差数列对象 repr() 打印形式字符串 reversed() 序列反向迭代器 round() 小数舍入 S set() 创建集合对象 setattr() 设置对象属性 slice() 切片对象 sorted() 返回已排序列表 staticmethod() 方法转换为静态方法 str() 对象的字符形式 sum() 求和 super() 调用超类方法 T tuple() 构建元组 type() 对象的类型 V vars() 对象属性字典 Z zip() 同位元素对象组合 - __import__() 导入模块 常用函数说明
len()
内置函数 len() 返回对象的长度元素个数。len(s) 中 s 实参可以是序列如 string、bytes、tuple、list 或 range 等或容器类型如 dictionary、set 或 frozen set 等。
len(abc) # 3
len([a, b, c]) # 3
len([]) # 0
len() # 0
len(range(3)) # 3
当您定义一个类时您可以定义的特殊方法之一是__len__()这些特殊方法被称为 dunder 方法因为它们在方法名称的开头和结尾都有双下划线。Python 的内置 len( )函数调用其参数的 __len__() 方法。因此可以为对象指定自定义长度如果需要。
class Session:def __init__(self, number 0):self.number numberdef __len__(self):return self.number# default length is 0
s1 Session()
print(len(s1))
# 0# giving custom length
s2 Session(6)
print(len(s2))
# 6type()
传入一个对象的字面量或者标识符将返回此对象的类型.
它有两种使用形式
class type(object)
class type(name, bases, dict, **kwds)
第一种形式
第一种形式传入一个参数时返回 object 的类型。 返回值是一个 type 对象通常与 object.__class__ 所返回的对象相同。
推荐使用 isinstance() 内置函数来检测对象的类型因为它会考虑子类的情况。
第二种形式
传入三个参数时返回一个新的 type 对象。 用来创建类。
这在本质上是 class 语句的一种动态形式
name 字符串即类名并会成为 __name__ 属性bases 元组包含基类并会成为 __bases__ 属性如果为空则会添加所有类的终极基类 object。dict 字典包含类主体的属性和方法定义它在成为 __dict__ 属性之前可能会被拷贝或包装。
下面两条语句会创建相同的 type 对象:
class X:a 1# 同上操作
X type(X, (), dict(a1))
类型对象表示各种对象类型。 对象的类型可通过内置函数 type() 来获取。 类型没有特殊的操作。 标准库模块 types 定义了所有标准内置类型的名称。类型以这样的写法来表示: class int。
提供给三参数形式的关键字参数会被传递给适当的元类机制 (通常为 __init_subclass__())相当于类定义中关键字 (除了 metaclass) 的行为方式。
可以利用 type() 传入三个参数的形式快速定义一个类
o1 type(X, (object,), dict(aFoo, b12))
print(type(o1))
print(vars(o1))‘’‘
class test:a Foob 12
’’’o2 type(Y, (test,), dict(aFoo, b12))
print(type(o2))
print(vars(o2))‘’‘
class type
{a: Foo, b: 12, __module__: __main__, __dict__: attribute __dict__ of X objects, __weakref__: attribute __weakref__ of X objects, __doc__: None}
class type
{a: Foo, b: 12, __module__: __main__, __doc__: None}
’‘’
vars() vars() 返回对象的属性和属性值的字典对象。如果没有参数就返回当前调用位置的属性和属性值行为类似 locals()。
语法为 vars([object])其中对象可有可没有。来用返回模块、类、实例或任何其它具有 __dict__ 属性的对象的 __dict__ 属性。
带参数的vars():
模块和实例这样的对象具有可更新的 __dict__ 属性但是其它对象的 __dict__ 属性可能会设为限制写入例如类会使用 types.MappingProxyType 来防止直接更新字典。
如果指定了一个对象但它没有 __dict__ 属性例如当它所属的类定义了 __slots__ 属性时则会引发 TypeError 异常。
不带参数的vars():
不带参数时vars() 的行为类似 locals() locals() 用来更新并返回表示当前本地符号表的字典。 请注意locals 字典仅对于读取起作用因为对 locals 字典的更新会被忽略。
如我们进行赋值操作时如 bar 1执行赋值语句后名称 bar 引用到值 1名字为键将我们要取这个值时可以用 vars() 返回的字典里用此键取得其引用值 # 在终端输入
vars()
# 输出已美化格式
{__name__: __main__,__doc__: None,__package__: None,__loader__: class _frozen_importlib.BuiltinImporter,__spec__: None,__annotations__: {},__builtins__: module builtins (built-in)
}# 1 对象没有__dict__ 属性
vars(1)
# TypeError: vars() argument must have __dict__ attributeclass Foo:def __init__(self):self.__dict__ {name:Foo}f Foo()
vars(f)
# {name: Foo}# 再终端执行
vars()
# 输出已美化格式
{__name__: __main__,__doc__: None,__package__: None,__loader__: class _frozen_importlib.BuiltinImporter,__spec__: None,__annotations__: {},__builtins__: module builtins (built-in),Foo: class __main__.Foo,f: __main__.Foo object at 0x7fccf35f5120
}
# 注意最后两项 isinstance()
内置函数 isinstance() 用来判断一个对象是否是一个已知的类型或者说检测对象是不是这个类型的实例、这个类的实例。如果要判断两个类型是否相同推荐使用 isinstance()。
语法为
isinstance(obj, class_or_tuple, /)
其中
object要检测判断的对象class_or_tuple被检测的类支持 classtypeclass 组成的元组types 模块中定义的 typeunion 类型
返回
布尔值返回对象是类的实例还是其子类的实例。
功能说明
如果 object 参数是 class_or_tuple 参数的实例或其直接、间接或抽象基类子类的实例则返回 True。如果 object 不是给定类型的对象则总是返回 False。如果 class_or_tuple 是类型对象的元组或由该类元组递归生成或多个类型的 union 类型那么当 object 是其中任一类型的实例时就会返回 True。如果 class_or_tuple 不是某个类型或类型元组将会触发 TypeError 异常。注在 3.10 版本开始class_or_tuple 可以是一个 union 类型。
如果 class_or_tuple 是元组那么以下相同
isinstance(x, (A, B, ...))
# 同上
isinstance(x, A) or isinstance(x, B) or ...
#内置类型
a 2isinstance(a,int)
# True
isinstance(a,str)
# False
isinstance(a,(str,int,list)) # 是否其中一个
isinstance(a, str | int | list)
# True#types 模块
import typesisinstance(None, types.NoneType)
# Trueisinstance(print, types.BuiltinFunctionType)
# True#自定义类
class Foo:a 5foo Foo()isinstance(foo, Foo) # True
isinstance(foo, (list, tuple)) # False
isinstance(foo, (list, tuple, Foo)) # True和type()的区别
区别总结为
type() 不会认为子类是一种父类类型不考虑继承关系isinstance() 会认为子类是一种父类类型考虑继承关系
关于 isinstance() 与 type() 的区别可以看以下示例
class A:passclass B(A):passisinstance(A(), A) # True
type(A()) A # True
isinstance(B(), A) # True
type(B()) A # False有人也用 type(variable) str 这种方式判断某个对象的类型虽然此方法是可行的但不提倡。
issubclass
内置函数 issubclass() 主要用于判断参数 class 是否是类型参数 classinfo 的子类。
语法
issubclass(cls, class_or_tuple, /)
参数说明
cls被检测的子类class_or_tuple是否 cls 的父类形式可以是 class、type 或者它们组成的元组 tuple元组的话只有一个满足即可
如果 cls 是 class_or_tuple 的子类直接、间接或抽象基类则返回 True。类被视为自身的子类。class_or_tuple 可以是类对象的元组或递归地其他此类元组或联合类型, 在这种情况下如果类是 class_or_tuple 中任何条目的子类则返回True。在任何其他情况下都会引发 TypeError 异常。
issubclass() 返回
True 如果类是类的子类或元组的任何元素False 都不是
在 3.10 版更改: class_or_tuple 可以是一个 union 类型联合类型可以用 | 符号连接。
class Polygon:def __init__(polygonType):print(Polygon is a , polygonType)class Triangle(Polygon):def __init__(self):Polygon.__init__(triangle)issubclass(Triangle, Polygon)
# True
issubclass(Triangle, list)
# False
issubclass(Triangle, (list, Polygon))
# True
issubclass(Polygon, (list, Polygon))
# True
需要注意的是类被视为自身的一个子类。
super()
super() 用于调用父类(超类)的一个方法用来解决多重继承问题的。不仅仅可以调用父类的构造函数还可以调用父类的成员函数。
语法如下
class super(self, /, *args, **kwargs)
# or
super(type[, object-or-type])
调用形式可以有以下几种
super() # 同 super(__class__, first argument)
super(type) # 未绑定超类对象
super(type, obj) # 绑定超类对象; 实现 isinstance(obj, type)
super(type, type2) # 绑定超类对象; 实现 issubclass(type2, type)
class Person(object):def eat(self, times):print(f我每天吃{times}餐。)class Student(Person):def eat(self):# 调用超类super().eat(4)tom Student()
tom.eat()
# 我每天吃4餐。Student.mro()
# [__main__.Student, __main__.Person, object]
调用超类方法的典型用法
class C(B):def meth(self, arg):super().meth(arg)也适用于类方法
class C(B):classmethoddef cmeth(cls, arg):super().cmeth(arg)
super() 返回一个代理对象它会将方法调用委托给 type 的父类或兄弟类。 这对于访问已在类中被重载的继承方法很有用。
object-or-type 确定用于搜索的 MRO (method resolution order)。 搜索会从 type 之后的类开始。
举例来说如果 object-or-type 的 __mro__ 为 D - B - C - A - object 并且 type 的值为 B则 super() 将会搜索 C - A - object。
object-or-type 的 __mro__ 属性列出了 getattr() 和 super() 所共同使用的方法解析搜索顺序。 该属性是动态的可以在任何继承层级结构发生更新的时候被改变。
如果省略第二个参数则返回的超类对象是未绑定的。 如果第二个参数为一个对象则 isinstance(obj, type) 必须为真值。 如果第二个参数为一个类型则 issubclass(type2, type) 必须为真值这适用于类方法。
super 有两个典型用例。 在具有单继承的类层级结构中super 可用来引用父类而不必显式地指定它们的名称从而令代码更易维护。 这种用法与其他编程语言中 super 的用法非常相似。
第二个用例是在动态执行环境中支持协作多重继承。 此用例为 Python 所独有而不存在于静态编码语言或仅支持单继承的语言当中。 这使用实现“菱形图”成为可能即有多个基类实现相同的方法。 好的设计强制要求这样的方法在每个情况下都具有相同的调用签名因为调用顺序是在运行时确定的也因为这个顺序要适应类层级结构的更改还因为这个顺序可能包括在运行时之前未知的兄弟类。
对于以上两个用例典型的超类调用看起来是这样的:
class C(B):def method(self, arg):super().method(arg) # This does the same thing as:# super(C, self).method(arg)除了方法查找之外super() 也可用于属性查找。 一个可能的应用场合是在上级或同级类中调用 描述器。
请注意 super() 是作为显式加点属性查找的绑定过程的一部分来实现的例如 super().__getitem__(name)。 它做到这一点是通过实现自己的 __getattribute__() 方法这样就能以可预测的顺序搜索类并且支持协作多重继承。 对应地super() 在像 super()[name] 这样使用语句或操作符进行隐式查找时则未被定义。
还要注意的是除了零个参数的形式以外super() 并不限于在方法内部使用。 两个参数的形式明确指定参数并进行相应的引用。 零个参数的形式仅适用于类定义内部因为编译器需要填入必要的细节以正确地检索到被定义的类还需要让普通方法访问当前实例。
super() 是用来解决多重继承问题的直接用类名调用父类方法在使用单继承的时候没问题但是如果使用多继承会涉及到查找顺序MRO、重复调用钻石继承等种种问题。MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
在类的继承中如果重定义某个方法该方法会覆盖父类的同名方法但有时我们希望能同时实现父类的功能这时我们就需要调用父类的方法了。
事实上对于你定义的每一个类Python 会计算出一个方法解析顺序Method Resolution Order, MRO列表它代表了类继承的顺序我们可以使用下面的方式获得某个类的 MRO 列表以页案例为例
Student.__mro__
Student().__class__.mro()
Student.mro()
# [__main__.Student, __main__.Person, object]这个列表真实的列出了类C的继承顺序。Student-Person-object。在方法调用时是按照这个顺序查找的。
那这个 MRO 列表的顺序是怎么定的呢它是通过一个 C3 线性化算法来实现的这里我们就不去深究这个算法了一个类的 MRO 列表就是合并所有父类的 MRO 列表并遵循以下三条原则
子类永远在父类前面如果有多个父类会根据它们在列表中的顺序被检查如果对下一个类存在两个合法的选择选择第一个父类
super 的工作原理如下
def super(cls, inst):mro inst.__class__.mro()return mro[mro.index(cls) 1]其中cls 代表类inst 代表实例上面的代码做了两件事
获取 inst 的 MRO 列表查找 cls 在当前 MRO 列表中的 index, 并返回它的下一个类即 mro[index 1]
当你使用 super(cls, inst) 时Python 会在 inst 的 MRO 列表上搜索 cls 的下一个类因此 super() 和父类没有实质性的关联。
比如在下列的菱形继承关系中C 的 MRO 列表是 C-A-B-Base-object Base/ \/ \A B\ /\ /C代码如
class Base(object):def __init__(self):print(enter Base)print(leave Base)class A(Base):def __init__(self):print(enter A)super(A, self).__init__()print(leave A)class B(Base):def __init__(self):print(enter B)super(B, self).__init__()print(leave B)class C(A, B):def __init__(self):print(enter C)super(C, self).__init__()print(leave C)c C()enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C
C.mro()
# [__main__.C, __main__.A, __main__.B, __main__.Base, object]enter A 的下一句不是 enter Base 而是 enter B原因是super 和父类没有实质性的关联是按照 mro 顺序运行的。
因此super() 的主要作用
允许我们避免显式使用基类名称 父类的名称是不固定的避免改名、改变继承方式省去修改代码传入的 arg 本身也是动态的比较灵活使用多重继承 object()
object() 函数返回一个空对象不能向该对象添加新属性或方法。这个对象是所有类的基础它拥有所有类默认的内置属性和方法。
o object()
哨兵值Sentinel value是一个特殊值(唯一)因为和所有其它值不同所以可以作为区分其它值得标记。
可以理解为它是一个唯一的占位符值在 Python 程序中对一些事情很有用例如函数参数的默认值其中没有一个是有效的输入值。
object() 的实例在其它任何地方都不会出现不会出现重复的可能 x object()o object()o is x
Falseo x
False
因些很多场景下用它做缺失值MISSING的替代。我们看这样的一个例子
sentinel object() # 用于指示缓存未命中的唯一对象
result cache_get(key, sentinel)
if result is not sentinel:... print()
print() 是 python 最美的语句它会将你知道的内容不知道在变量里的内容打印输出。
语法为
print(*objects, sep , end\n, filesys.stdout, flushFalse)
它将值打印到流或 sys.stdout默认。其中 objects 是一个序列对象语法表示中可见它可以被解包其他可选的关键字参数有
file: 类似文件的对象流默认为当前系统的 sys.stdoutsep: 在输出的值之间插入分隔字符串默认为空格end: 最后一个值后追加的字符串默认为换行符flush: 是否强制刷新
以上四个参数必须以关键字参数的形式给出所有非关键字参数都会被转换为字符串就像是执行了 str() 一样并会被写入到流以 sep 且在末尾加上 end。 sep 和 end 都必须为字符串它们也可以为 None这意味着使用默认值。 如果没有给出 objects则 print() 将只写入 end。
file 参数必须是一个具有 write(string) 方法的对象如果参数不存在或为 None则将使用 sys.stdout。 由于要打印的参数会被转换为文本字符串因此 print() 不能用于二进制模式的文件对象。 对于这些对象应改用 file.write(...)。输出是否缓存通常取决于 file但如果 flush 关键字在 3.3 版新增参数为 True输出流会被强制刷新。
pi 3.14print(pi)
# 3.14
#输出多个内容
print(圆周率, pi)
# 圆周率 3.14
#中间用空格分隔变量也帮我们打印出了具体的值。试试看以下代码print(8848, 新的高度。)
print(1, 2, 3, 4)
print(盖若, 是个好网站)
print(---------)
#连接
print(圆周率, pi, sep:)
# 圆周率:3.14
#两个值之间多了个: 分隔。试试以下代码print(1, 2, 3, 4, sep-)
# 1-2-3-4
print(1, 2, 3, 4, sep\n) # \n 代表换行1
2
3
4print(1, 2, 3, 4, sep\t) # \t 代表一个制表符号就是 tab
# 1 2 3 4#结尾连接
print(1, end )
print(2, end )
# 1 2
flush 参数示例
如同 C 语言print() 使用标准输出。这不过是操作系统中的“文件”程序的文本输出在操作系统中发送因此可以显示给用户。
默认情况下stdout 是缓冲的。也就是说在收到特殊换行代码 \n 之前它会存储接收到的数据而不显示数据。Python 的 print 函数会自动增加换行符给发送给它的任何字符串。但有时这种行为是不可取的你想在同一行上显示多个东西。
在下例中将使用 print 函数的 end 参数以换行符以外的字符或空字符串结束字符串这样您就不会打印除所要求的内容之外的任何内容。以下代码在同一行上打印几个点每 0.5s 打印一个点注意在终端中执行不要在 Notebook
# 参考https://itqna.net/questions/37569/what-print-flush-python-closed
import timefor _ in range(5):print(., end)time.sleep(0.5)
print( Gairuo!)# 在终端中最后一次性显示
# ..... Gairuo!
但在大多数情况下2.5 秒内什么也没发生然后所有的点都同时出现。这是因为在默认情况下stdout 在接收到新行之前不会显示任何内容而我们直到最后才会发送新行。那么我们如何解决这个问题呢很简单只需使用 flush 强制立即显示结果即使没有新行
import timefor _ in range(5):print(., end, flushTrue)time.sleep(0.5)
print( Gairuo!)# 依次显示以下内容
# ..... Gairuo!
值得一提的是flush 作为 print 的增强参数仅在Python 3.3 中提供。在此之前它必须手动调用
import sys
import timefor _ in range(5):print(., end)sys.stdout.flush() # 这儿time.sleep(0.5)
print( Gairuo!)
这个 flush 参数可以帮我们做出类似执行进度条之类的功能。
使用场景
尤其是在 while 循环中要想每进行一次 while 循环体在屏幕上更新打印的内容就得使用 flushTrue 的参数。打开一个文件 向其写入字符串 在关闭文件 f.close() 之前 打开文件可能是看不到写入的字符的 要想在关闭之前实时的看到写入的字符串应该用 flushTrue input()
内置函数 input() 函数接受一个标准输入数据返回为 string 类型。它用于从控制台读取用户输入的内容一般在交互模式下让用户通过输入来控制程序。
它的语法是 input([prompt])可选参数 prompt 起到提示作用可以告诉用户如何输入输入什么格式。
如果存在 prompt 实参则将其写入标准输出末尾不带换行符。接下来该函数从输入中读取一行将其转换为字符串除了末尾的换行符并返回。当读取到 EOF 时则触发 EOFError。
如果加载了 readline 模块input() 将使用它来提供复杂的行编辑和历史记录功能。
引发一个 审计事件 builtins.input 附带参数 prompt。
在成功读取输入之后引发一个审计事件 builtins.input/result 附带结果。 s input(-- )
# --
# 此时提示用户输入我们输入Monty Pythons Flying Circuss
Monty Pythons Flying Circus”age int(input(你哪年出生))
print(f你的年龄为{2022-age})# 你哪年出生
# 输入 2000回车
# 输出
# 你的年龄为22 range()
range对象
range 对象是rangeobject Python 内置的对象它可以认为是一个不可变的数字序列通常用于在 for 循环中指定循环的次数。虽然被称为函数但 range 实际上是一个不可变的序列类型。
语法
range(stop)
range(start, stop[, step])
参数
start: 可选数列的开始默认从 0stop: 必传数列的结束不包含step: 可选步长默认是 1
参数说明
以上三个参数必须是整数integers或者内置 int 类型以及任何实现 __index__() 特殊方法的对象如果省略 step 参数则默认为 1如果省略 start 参数则默认为 0如果步长为零则会引发 ValueError
生成规则
如果 step 为正值确定 range r 内容的公式为 r[i] start step*i 其中 i 0 且 r[i] stop。如果 step 为负值确定 range 内容的公式仍然为 r[i] start step*i但限制条件改为 i 0 且 r[i] stop。如果 r[0] 不符合值的限制条件则该 range 对象为空。 range 对象确实支持负索引但是会将其解读为从正索引所确定的序列的末尾开始索引。元素绝对值大于 sys.maxsize 的 range 对象是被允许的但某些特性 (例如 len()) 可能引发 OverflowError。
特点
相比常规 list 或 tuplerange 对象总是占用固定数量的较小内存不论其所表示的范围有多大因为它只保存了 start、stop 和 step 值并会根据需要计算具体单项或子范围的值。
属性和方法
range() 函数创建的 rangeobject有三个属性
# 定义范围对象 rangeobject
r range(1, 10, 2)
list(r) # 转为列表
# [1, 3, 5, 7, 9]# 属性
r.start # 1 开始值
r.stop # 10 终止值
r.step # 2 步长# 返回值的出现次数
r.count(1) # 1
r.count(10) # 0# 返回值的索引
r.index(3) # 1
# 如果该值不存在则引发值错误
r.index(10) # ValueError: 10 is not in range
使用
可用列表推导式来展开 range 对象
[i for i in range(4)] # [0, 1, 2, 3]
用在 for 循环中
for i in range(2, 10, 2):print(i, end )# 4 6 8
如果不知道要生成多长的 range, 可以通过 len() 来获取长度
var hello
for i in range(len(var)):print(var[i])
也可以使用len函数来获取range可以获得的列表的长度
r range(1, 10)
print(list(r))
print(list(r))
print(len(r))
r range(1, 15)
print(len(r))‘’’
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
9
14
’‘’
range 对象是序列(Sequence)
range对象实现了 collections.abc.Sequence 抽象基类ABC提供如包含检测、元素索引查找、切片等特性并支持负索引。
from collections import abcisinstance(r, abc.Sequence)
# Truetype(r)
# rangeissubclass(range, abc.Sequence)
# True
range 对象实现了 一般 序列的所有操作但拼接和重复除外这是由于 range 对象只能表示符合严格模式的序列而重复和拼接通常都会违反这样的模式。
r range(0, 20, 2)
r
# range(0, 20, 2)
list(r)
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
len(r)
# 10
max(r)
# 18
sum(r)
# 90
iter(r)
# range_iterator at 0x7f9b3a7ad4a0
11 in r
# False
10 in r
# True
r.index(10)
# 5
r[5]
# 10
r[:5]
# range(0, 10, 2)
r[-1]
# 18
不支持拼接和重复
r [1,2]
# TypeError: unsupported operand type(s) for : range and listr r
# TypeError: unsupported operand type(s) for : range and ranger*3
# TypeError: unsupported operand type(s) for *: range and int使用 和 ! 检测 range 对象是否相等是将其作为序列来比较。 也就是说如果两个 range 对象表示相同的值序列就认为它们是相等的。 请注意比较结果相等的两个 range 对象可能会具有不同的 start, stop 和 step 属性例如 range(0) range(2, 1, 3) 而 range(0, 3, 2) range(0, 4, 2)。 all()
all() 的作用是如果传入的可迭代对象的所有元素均为真值或可迭代对象为空则返回 True。它与any()有着不同的逻辑。
语法为
all(iterable)
iterable可迭代对象可以是任意的可迭代对象 (list, tuple, dictionary, 等)包含一定数量的元素。
返回
all() 函数中如果给定 iterable 可迭代对象中的所有元素
True - 如果 iterable 中的所有元素都为 trueFalse - 如果 iterable 中的任何元素为 false至少有一个为 False
注元素除了是 0、空、None、False 外都算 True空元组、空列表返回值为True要特别注意。 如果我们检测变量以下情况会得到假其他情况为真。 None, False数值中的 0,0.0, 0j(虚数), Decimal(0), Fraction(0, 1)空字符串 、空元组 ()、空列表 []空字典 {}、空集合 set()类的对象特殊方法 __bool__() 返回 False 或是定义了 __len__() 方法且返回 0 all()函数等价于
def all(iterable):for element in iterable:if not element:return Falsereturn True
以下是 all() 返回值参照表
情况返回值所有值为 trueTrue所有值为 falseFalse一个值为 true (其他为 false)False一个值为 false (其他为 true)False空的可迭代对象True字符串包括空串True字典所有键为 trueTrue字典一个键为 falseFalse
注对于字典如果所有键不是值都为 true 或字典为空则 all() 返回 true。否则对于所有其他情况它将返回 false。
以下是一些案例
# 所有值为 true
iterable [1, 2, 3, 4]
all(iterable) # True# 所有值为 false
iterable [0, False]
all(iterable) # False# 一个为 true
iterable [0, False, 1]
all(iterable) # False# 一个为 false
iterable [1, 3, 4, 0]
all(iterable) # False# 空对象
iterable ()
all(iterable) # True# 字符串
iterable Hello
all(iterable) # True# 字典
d {0: False, 1: False}
all(d) # Falseall([False, None, 0, 0.0, 0 0j, , [], {}, ()])
# Truenot all([False, False, False])
# Falsenot all([True, False, False])
# True# 列表推导式
l [0, 1, 2, 3, 4]
all([i 2 for i in l])
# False
any([i 2 for i in l])
# True# 可以直接在生成器上使用比列表快很多
(i 2 for i in l)
# generator object genexpr at 0x7fe33e7e3dd0
all(i 2 for i in l)
# False
any(i 2 for i in l)
# True any()
any() 的作用是如果传入的可迭代对象的至少一个元素为真值则返回 True
语法形式为
any(iterable) 函数接受单个参数
iterable可迭代对象可以是任意的可迭代对象 (list, tuple, string, dictionary, 等)包含一定数量的元素。
返回
any() 函数中如果给定 iterable 可迭代对象中的所有元素
True - 如果 iterable 中至少有一个元素为 trueFalse - 如果所有元素都为 false 或 iterable 为空
注元素除了是 0、空、None、False 外都算 True空元组、空列表返回值为True要特别注意。 如果我们检测变量以下情况会得到假其他情况为真。 None, False数值中的 0,0.0, 0j(虚数), Decimal(0), Fraction(0, 1)空字符串 、空元组 ()、空列表 []空字典 {}、空集合 set()类的对象特殊方法 __bool__() 返回 False 或是定义了 __len__() 方法且返回 0 any()函数等价于
def any(iterable):for element in iterable:if element:return Truereturn False
any()函数返回值参照表
情况返回值所有值为 trueTrue所有值为 falseFalse一个值为 true (其他为 false)True一个值为 false (其他为 true)True空的可迭代对象False字符串不包括空串True空字符串False字典所有键为 trueTrue字典一个键为 false False
注对于字典如果所有键不是值都为 false 或字典为空any() 将返回 false。如果至少有一个键为 trueany() 将返回 true。 以下是一些案例
# True since 1,3 and 4 (at least one) is true
l [1, 3, 4, 0]
any(l) # True# False since both are False
l [0, False]
any(l) # False# True since 5 is true
l [0, False, 5]
any(l) # True# False since iterable is empty
l []
any(l) # False# Atleast one (in fact all) elements are True
s This is good
any(l) # True# 0 is False
# 0 is True since its a string character
s 000
any(l) # True# False since empty iterable
s
any(l) # False# 0 is False
d {0: False}
any(l) # False# 1 is True
d {0: False, 1: True}
any(l) # True# 0 and False are false
d {0: False, False: 0}
any(l) # False# iterable is empty
d {}
any(l) # False# 0 is False
# 0 is True
d {0: False}
any(l) # Trueany([False, None, 0, 0.0, 0 0j, , [], {}, ()])
# Falsenot any([False, False, False])
# Truenot any([True, False, False])
# False# 列表推导式
l [0, 1, 2, 3, 4]
all([i 2 for i in l])
# False
any([i 2 for i in l])
# True# 可以直接在生成器上使用比列表快很多
(i 2 for i in l)
# generator object genexpr at 0x7fe33e7e3dd0
all(i 2 for i in l)
# False
any(i 2 for i in l)
# True
max()和min()
内置函数 max() 可传入一个可迭代对象 或者多个元素作为参数返回这个它们中的最大元素。同样min() 可得到最小值。内置函数 min() 与 max() 的逻辑相同区别仅为返回最小的项这里仅以max()为例说明。
语法
max(iterable, *[, defaultobj, keyfunc]) - value
max(arg1, arg2, *args, *[, keyfunc]) - value
非数字类型如果判断大小可以参考 sorted() 中的排序原理。
第一种可迭代对象
如果只提供了一个位置参数它必须是非空 iterable返回可迭代对象中最大的元素使用单个 iterable 参数返回其最大项。如果提供的 iterable 为空则默认的仅关键字参数指定要返回的对象。其中
iterable可迭代对象如列表、元素、字典等等*iterables (可选)任意数量的序列如果我们传递多个序列则返回给定所有序列中最大的项key (可选)传递 iterables 并根据其返回值执行比较的关键函数default (可选)如果给定的 iterable 为空则为此默认值不传此值则不允许 iterable 为空对象
第二种多值
如果提供了两个最少及以上的位置参数则返回最大的位置参数。
max(arg1, arg2, *args, *[, keyfunc]) - value这种形式的参数为
arg1要对比的对象可以是数字、字符串等arg2要对比的对象可以是数字、字符串等*args (可选) 任意数量的对象注意前边两个参数是必传的key (可选) 传递每个参数并根据其返回值执行比较的键函数
max() 函数会在两个或多个对象之间查找最大的项。
key 实参指定排序函数用的参数如传给 list.sort() 的。default 实参是当可迭代对象为空时返回的值。如果可迭代对象为空并且没有给 default 则会触发 ValueError。
如果有多个最大元素则此函数将返回第一个找到的。这和其他稳定排序工具如 sorted(iterable, keykeyfunc, reverseTrue)[0] 和 heapq.nlargest(1, iterable, keykeyfunc) 保持一致。
可参考 sorted() 中关于 key 参数的介绍。 max(1,2,3) # 3max(123) # 3
max(1, 2, 3) # 3
max(abc) # cd {a: 3, b: 2, c: 1}
max(d) # c
max(d.items()) # (c, 1)
max(d, keylambda k: d[k]) # amax([22, 2], [42, 1]) # [42, 1]
max([(1,5),(2,4),(3,3)]) # (3, 3)
max([(1,5),(2,4),(3,3)], keylambda x: x[1])
# (1, 5)
max([*range(2)], [*range(7)])
# [0, 1, 2, 3, 4, 5, 6]max(0, True, -1) # True, True 为 1
max(range(10)) # 9max([], default10) # 10 class P():def __init__(self, name, age) - None:self.name nameself.age agedef __lt__(self, other):if self.age other.age:return Truedef __str__(self) - str:return f{self.name}, {self.age}a P(tom, 18)
b P(lily, 19)print(max(a, b)) # lily, 19
print(min(a, b)) # tom, 18
sum()
将一个序列的所有值进行求和并返回同时如果需要从一个固定值起始计算可以指定 start 参数。
语法是
sum(iterable, /, start0)
参数有
iterable可迭代对象如列表、元组、集合将会对这些数据进行相加或者连接start起始值保底值从此值开始再加上序列中的所有值默认为 0。
此函数专门用于数值可能会拒绝非数值类型。
内置函数 sum 相当于
def sum(values, start0):total startfor value in values:total total valuereturn totalzip()
内置函数 zip() 上用来创建一个聚合了来自每个可迭代对象中的元素的迭代器。它获取 iterables可以是零或更多将它们聚合成多个元组形成的可迭代对象然后返回。
语法为
zip(*iterables)
参数 iterables 可以是一个内置的可迭代对象 (如: list, string, dict), 或者是用户自己定义的可迭代对象。简单说就是可以传入一个或者多个一般是两个类似列表或者元组那样的可迭代对象如 zip([1,2], [3,4])等。同时它还支持参数为空。
返回一个基于参数 iterable 对象的元组迭代器zip 对象。根据传入参数的情况它返回的内容分别为
不传递任何参数将返回一个空迭代器zip 对象传递一个可迭代对象返回一个元组迭代器每个元组只有一个元素传递多个可迭代对象返回一个元组迭代器每个元组都包含来自所有 iterables 的元素, 迭代器在最短 iterable 耗尽时停止。
针对第三种情况如一个包含 2 个元素另一个包含 3 个元素则返回的迭代器将包含 2 个元组每个元组以第一个元组的 2 个元素开头传入的第二个元组的最后一个数据被丢弃。
# 无传入
z zip()
z # zip at 0x7fe33d1ac440
list(z)
# []# 传入一个
z zip([1,2,3])
list(z)
# [(1,), (2,), (3,)]# 传入两个
z zip([1,2,3],[3,4,5])
list(z)
# [(1, 3), (2, 4), (3, 5)]# 不同长度
z zip([1,2],[3,4,5])
list(z)
# [(1, 3), (2, 4)]z zip([1,2,3],[4,5])
list(z)
# [(1, 4), (2, 5)]# 解包
coordinate [x, y, z]
value [3, 4, 5]result zip(coordinate, value)
result_list list(result)
result_list
# [(x, 3), (y, 4), (z, 5)]c, v zip(*result_list)
c # (x, y, z)
v # (3, 4, 5)
在日常应用中我们一般按照一定的顺序将不同事物的数据存起来比如我们将 lily、lucy、amy 的身高、体重、年龄按顺序存起来形成三个列表
# 分别是每个人的 身高、体重、年龄
lily [168, 50, 22]
lucy [170, 55, 25]
amy [175, 53, 24]由于每个列表是单一女生的数据我们求平均身高时可以先操作 zip
z zip(lily,lucy,amy)
list(z)
# [(168, 170, 175), (50, 55, 53), (22, 25, 24)]此时返回的列表中的第一个值就是所有的身高数据就可以方便地计算出结果
z zip(lily,lucy,amy)
h list(z)[0]
sum(h)/3
# 171.0其他案例
names [Alice, Bob, Charlie]
ages [24, 50, 18]for name, age in zip(names, ages):print(name, age)
# Alice 24
# Bob 50
# Charlie 18另外zip 对象也可使我们方便地迭代组合信息。
我们知道如果传入的多个可迭代对的长度不相等则取最短的进行对应这类似于木桶效应的短板现象如果想按最长的处理不足的用 None 补足补齐可以使用 itertools 中的 zip_longest 方法
import itertoolsz itertools.zip_longest([1,2],[3,4,5])
list(z)
# [(1, 3), (2, 4), (None, 5)]
str() str() 返回对象的字符形式它是 str 版本的 object。str 是内置的字符串类一般用它来将对象转为字符类型。
str() 的语法是
class str(object)
class str(objectb, encodingutf-8, errorsstrict)
参数说明
object - 要返回其字符串表示形式的对象如果未提供则返回空字符串encoding - 给定对象的编码默认值 UTF-8errors - 解码失败时的响应。默认为 strict 严格的可选择以下 6 种 strict - 在失败时引发 UnicodeDecodeError 异常的默认响应ignore - 忽略结果中不可编码的 Unicodereplace - 将不可编码的 Unicode 替换为问号xmlcharrefreplace - 插入 XML 字符引用而不是不可编码的 Unicodebackslashreplace - 插入 \uNNNN 空间序列而不是不可编码的 Unicodenamereplace - 插入 \N{…} 转义序列而不是不可编码的 Unicode
返回
返回一个字符串该字符串被认为是给定对象的非正式或可打印的表示形式。
如果 encoding 或 errors 均未给出str(object) 返回 object.__str__()这是 object 的“非正式”或格式良好的字符串表示。 对于字符串对象这是该字符串本身。 如果 object 没有 __str__() 方法则 str() 将回退为返回 repr(object)。
如果 encoding 或 errors 至少给出其中之一则 object 应该是一个 bytes-like object (例如 bytes 或 bytearray)。 在此情况下如果 object 是一个 bytes (或 bytearray) 对象则 str(bytes, encoding, errors) 等价于 bytes.decode(encoding, errors)。 否则的话会在调用 bytes.decode() 之前获取缓冲区对象下层的 bytes 对象。
将一个 bytes 对象传入 str() 而不给出 encoding 或 errors 参数的操作属于第一种情况 将返回非正式的字符串表示
str(88)
# 88str(Gairuo!)
# Gairuo!str(bGairuo!)
# bGairuo!# bytes
b bytes(gairuö, encodingutf-8)
str(b, encodingascii, errorsignore)
# gairu在上边 bytes 实例中字符“ö”不能被 ASCII 解码。因此它应该给出一个错误。但是我们已将错误设置为“忽略”。因此Python会忽略 str() 无法解码的字符。 自定义字符形式
通过对象类的特殊方法 object.__str__() 可以自定义返回的字符内容
class Student(object):def __init__(self, name):self.name namedef __str__(self):return repr(f我是{self.name})me Student(大明)
str(me)
# 我是大明 repr()
repr 是 representation描述、表现形式的缩写对象的 repr 的目的是返回可以包含在表达式中的字符串其中同一对象的 str 是可以自然显示的字符串。
print(repr(a))
print({!r}.format(a))
print(%r%a) 上边代码的 r 是 repr 的缩写。repr 在调试代码时最有用尤其是在编写自己的自定义代码时。 repr(object) 返回对象的可打印形式字符串。对于很多类型而言本函数试图返回的字符串会与将对象传给 eval() 所生成的结果相同。
它的语法形式是 repr(object) 传入的是一个任意的对象返回的给定对象的可打印表示形式。对于许多类型此函数尝试返回一个字符串该字符串将在传递给 eval() 时生成具有相同值的对象否则表示是一个尖括号中的字符串其中包含对象类型的名称以及其他信息通常包括对象的名称和地址见下例。类对象可以通过定义特殊方法 _repr__() 方法来控制此函数为其实例返回的内容。
以下是定义了一个整型对象我们用 repr() 返回它的打印形成它是一个字符串当我们将这个结果传给 eval() 时它生成一个原来的整型对象
n 10
repr(n)
# 10eval(repr(n))
# 10
其他例子
repr(True)
# Truerepr(bool)
# class boolimport math
repr(math)
# module math from ../math.cpython-310-darwin.sorepr(repr)
# built-in function reprimport pandas as pd
repr(pd.Series)
# class pandas.core.series.Seriesimport numpy as np
repr(np.array([*abc]))
# array([a, b, c], dtypeU1)repr(__name__)
# __main__repr(int|str)
# int | str# 自定义类
class student:passrepr(student())
# __main__.student object at 0x7fec2f1d2080
自定义__repr__
通过重载特殊方法 __repr__() 可自定义对象的 repr() 返回值。
class Student(object):def __init__(self, name):self.name namedef __repr__(self):return repr(f我是{self.name})me Student(大明)
repr(me)
# 我是大明
repr() 返回的有得于解释器读取的形式string 格式因此将 string 格式可以传给 eval() 进行执行。
如果我们使用 repr() 函数打印字符串然后它会用一对引号打印如果我们计算一个值我们会得到比 str() 函数更精确的值。
str() 与repr()的区别
str() 用于为最终用户创建输出而 repr() 主要用于调试和开发。 repr() 的目标是明确无误str() 的目标是可读性。例如如果我们怀疑一个浮点数有一个小的舍入误差repr 将显示给我们而 str 可能没有。repr() 计算对象的“正式”的字符串表示形式包含该对象的所有信息的表示形式str() 用于计算对象的“非正式”友好的字符串表示形式用于打印该对象的表示形式。print() 打印语句的 str() 内置特殊函数使用 __str__ 显示对象的字符串表示形式页 repr() 内置特殊函数使用 __repr__ 以显示对象。
import datetime
now datetime.datetime.now()# 打印日期时间对象的可读格式
print(now)
str(now)
# 2021-11-10 22:47:52.471301# 打印日期时间对象的正式格式
repr(now)
# datetime.datetime(2021, 11, 10, 22, 47, 52, 471301) eval() eval() 将会执行执行一个以字符串为形式的 Python 表达式。 他非常强大同时也非常危险所以我们在使用时要格外小心。
eval() 的语法
eval(source, globalsNone, localsNone, /)
在全局 globals() 和局部 locals() 命名空间的上下文中计算执行给定的 source 字符串表达式。
source 可以是表示Python表达式的字符串也可以是 compile() 返回的代码对象。 全局变量 globals 必须是字典局部变量 locals 可以是任何映射类型默认为当前全局变量和局部变量。 如果只提供 globals则 locals 默认也是它。
即
expression 类型可以是 str、bytes、CodeType要执行表达式或者代码。globals 可选参数)变量作用域全局命名空间如果被提供则必须是一个字典对象。locals (可选参数)变量作用域局部命名空间如果被提供可以是任何映射对象。 eval(12)
# 3a 2
eval(a*4)
# 8eval([*123])
# [1, 2, 3]eval({a:1})
# {a: 1}eval({b: c}, {c:10})
# {b: 10}eval([i for i in range(2)])
# [0, 1]
表达式解析参数 expression 并作为 Python 表达式进行求值从技术上说是一个条件列表采用 globals 和 locals 字典作为全局和局部命名空间。 如果存在 globals 字典并且不包含 __builtins__ 键的值则在解析 expression 之前会插入以该字符串为键以对内置模块 builtins 的字典的引用为值的项。 这样就可以在将 globals 传给 eval() 之前通过向其传入你自己的 __builtins__ 字典来控制可供被执行代码可以使用哪些内置模块。 如果 locals 字典被省略则它默认为 globals 字典。 如果两个字典都被省略则将使用调用 eval() 的环境中的 globals 和 locals 来执行该表达式。 注意eval() 无法访问闭包环境中的 嵌套作用域 (非局部变量)。
返回值就是表达式的求值结果。 语法错误将作为异常被报告。
该函数还可用于执行任意代码对象比如由 compile() 创建的对象。 这时传入的是代码对象而非一个字符串了。如果代码对象已用参数为 mode 的 exec 进行了编译那么 eval() 的返回值将为 None。
提示 exec() 函数支持语句的动态执行。 globals() 和 locals() 函数分别返回当前的全局和本地字典可供传给 eval() 或 exec() 使用。
如果给出的源数据是个字符串那么其前后的空格和制表符将被剔除。
# 在指定命名空间中执行表达式
namespace {a: 2, b: 3}
result eval(a b, namespace)
print(result) # 输出: 5#eval传递全局变量参数,注意字典里的:age中的age没有带引号说明它是个变量而不是字符串。
#这里两个参数都是全局的
print(eval({name:linux,age:age},{age:1822}))
#输出结果{name: linux, age: 1822}
print(eval({name:linux,age:age},{age:1822},{age:1823}))
#输出结果{name: linux, age: 1823}#eval传递本地变量既有global和local时变量值先从local中查找。
age18
print(eval({name:linux,age:age},{age:1822},locals()))
#输出结果{name: linux, age: 18}
print(-----------------)print(eval({name:linux,age:age}))
使用风险
考虑使用 UNIX 系统Mac OSLinux等的情况然后导入 OS 模块。操作系统模块提供了一种可移植的方式来使用操作系统功能如读取或写入文件。如果允许用户使用 eval(input()) 输入一个值则用户可以使用命令os 发出命令来更改文件甚至删除所有文件os.system(rm -rf *)。警告千万别试啊
eval 虽然方便但是 要注意安全性可以将字符串转成表达式并执行就可以利用执行系统命令删除文件等操作。比如用户恶意输入就会获得当前目录文件。
我们可以适当限制命名空间
from math import *
eval(dir())
# 所有 math 的命名空间eval(dir(), {})
# [__builtins__]eval(dir(), {sqrt: sqrt, pow: pow})
# [__builtins__, pow, sqrt]# 禁止内置命名空间内置函数等
eval(dir(), {__builtins__: None})
# TypeError: NoneType object is not subscriptable
注意有时eval() 即使名称有限也不安全。当一个对象及其方法可以访问时几乎任何事情都可以完成。唯一安全的方法是验证用户输入。
ast.literal_eval
在 Python 中eval() 函数可以将字符串作为代码执行。但是使用 eval() 函数时需要非常小心因为它可以执行任何代码包括恶意代码。为了确保安全可以使用 ast.literal_eval() 函数来代替 eval() 函数。ast.literal_eval() 函数只能评估一些基本的 Python 表达式例如字符串、数字、元组、列表、字典和布尔值因此它比 eval() 函数更安全。
ast.literal_eval(node_or_string) 计算表达式节点或仅包含Python表达式的字符串。提供的字符串或节点只能由以下Python文本结构组成字符串、字节、数字、元组、列表、dicts、set、boolean 和 None。
compile()
compile() 函数将指定的源普通字符串、字节串或 AST 对象作为代码对象返回。 compile() 方法返回的代码对象可以使用 exec() 和 eval() 等方法调用它们将执行动态生成的 Python 代码。
语法
compile(source,filename,mode,flags0,dont_inheritFalse,optimize-1,*,_feature_version-1,
)
参数说明
source - 源代码可以表示 Python 模块、语句或表达式包括 string、byte string、AST objectfilename - 从中读取代码的文件。如果它不是从文件中读取的你可以自己给它起个名字mode - 字符串exec 或 eval 或 single。 eval - 只接受一个表达式。exec - 它可以采用包含Python语句、类和函数等的代码块single - 如果它由单个交互语句组成flags (可选) - 控制未来哪些语句会影响源代码的编译。默认值0dont_inherit (可选) - 如果为true则会停止继承代码调用中任何未来有效语句效果的编译optimize (可选) - 编译器的优化级别。默认值为-1。
将源代码编译成可由 exec() 或 eval()执行的代码对象。 codeInString a 5\nb6\nsumab\nprint(sum ,sum)
codeObejct compile(codeInString, sumstring, exec)exec(codeObejct)
# sum 11eval(codeObejct)
# sum 11
由 compile() 生成的代码对象可以由内置函数 eval() 和exec()执行并得到执行结果。 compile() 将 source 编译成代码或 ASTAbstract Syntax Trees 对象。代码对象可以被 exec() 或 eval() 执行。source 可以是常规的字符串、字节字符串或者 AST 对象。
filename 实参需要是代码读取的文件名如果代码不需要从文件中读取可以传入一些可辨识的值经常会使用 string。
mode 实参指定了编译代码必须用的模式。如果 source 是语句序列可以是 exec如果是单一表达式可以是 eval如果是单个交互式语句可以是 single。在最后一种情况下如果表达式执行结果不是 None 将会被打印出来。
可选参数 flags 和 dont_inherit 控制应当激活哪个 编译器选项 以及应当允许哪个 future 特性。 如果两者都未提供 (或都为零) 则代码会应用与调用 compile() 的代码相同的旗标来编译。 如果给出了 flags 参数而未给出 dont_inherit (或者为零) 则会在无论如何都将被使用的旗标之外还会额外使用 flags 参数所指定的编译器选项和 future 语句。 如果 dont_inherit 为非零整数则只使用 flags 参数 -- 外围代码中的旗标 (future 特性和编译器选项) 会被忽略。
编译器选项和 future 语句是由比特位来指明的。 比特位可以通过一起按位 OR 来指明多个选项。 指明特定 future 特性所需的比特位可以在 __future__ 模块的 _Feature 实例的 compiler_flag 属性中找到。 编译器旗标 可以在 ast 模块中查找带有 PyCF_ 前缀的名称。
optimize 实参指定编译器的优化级别默认值 -1 选择与解释器的 -O 选项相同的优化级别。显式级别为 0 没有优化__debug__ 为真、1 断言被删除 __debug__ 为假或 2 文档字符串也被删除。
如果编译的源码不合法此函数会触发 SyntaxError 异常如果源码包含 null 字节则会触发 ValueError 异常。
如果您想分析 Python 代码的 AST 表示请参阅 ast.parse()。
引发一个 审计事件 compile 附带参数 source, filename。
在 single 或 eval 模式编译多行代码字符串时输入必须以至少一个换行符结尾。 这使 code 模块更容易检测语句的完整性。
在将足够大或者足够复杂的字符串编译成 AST 对象时Python 解释器有可能因为 Python AST 编译器的栈深度限制而崩溃。 exec()
函数 exec() 可执行储存在字符串或文件中的 Python语句相比于 evalexec 可以执行更复杂的 Python 代码。exec 返回值永远为 None除非你打印返回值。它是 Python 留给用户的一个接口。
语法
exec(source, globalsNone, localsNone, /)
参数说明
在全局 globals() 和局部 locals() 命名空间的上下文中计算执行给定的 source 字符串表达式返回值永远为 None。
source 可以是表示Python表达式的字符串也可以是compile()返回的代码对象。 全局变量 globals 必须是字典局部变量 locals 可以是任何映射类型默认为当前全局变量和局部变量。 如果只提供 globals则 locals 默认也是它。 exec(a1\nb1\nprint(ab))
# 2exec(n22)
n
# 4
此函数支持Python代码的动态执行。对象必须是字符串或代码对象。如果它是一个字符串该字符串将被解析为一组 Python 语句然后执行除非出现语法错误。如果它是一个代码对象则只需执行它。在所有情况下执行的代码都应作为文件输入有效请参阅第节文件输入 在参考手册中。请注意nonlocal、yield 和 return 语句不能在函数定义之外使用甚至不能在传递给 exec() 函数的代码上下文中使用。返回值为 None。
解析器只接受 Unix 风格的行结束符。如果您从文件中读取代码请确保用换行符转换模式转换 Windows 或 Mac 风格的换行符。
无论在什么情况下如果省略了可选部分代码将运行于当前作用域中。如果只提供了 globals则必须为字典对象而不能是字典的子类同时用于存放全局变量和局部变量。如果提供了 globals 和 locals则将分别用于全局变量和局部变量。locals 可以是任意字典映射对象。请记住在模块级别globals 和 locals 是同一个字典。如果 exec 获得两个独立的对象作为 globals 和 locals代码执行起来就像嵌入到某个类定义中一样。
如果 globals 字典不包含 __builtins__ 键值则将为该键插入对内建 builtins 模块字典的引用。因此在将执行的代码传递给 exec() 之前可以通过将自己的 __builtins__ 字典插入到 globals 中来控制可以使用哪些内置代码。
如果出现错误将引发一个 审计事件 exec 附带参数 code_object。
注意
内置 globals() 和 locals() 函数各自返回当前的全局和本地字典因此可以将它们传递给 exec() 的第二个和第三个实参。默认情况下locals 的行为如下面 locals() 函数描述的一样不要试图改变默认的 locals 字典。如果您想在 exec() 函数返回时知道代码对 locals 的变动请明确地传递 locals 字典。
需要注意的是exec() 执行代码不返回任何值返回 None。因此不能在函数定义之外使用 return 和 yield 语句。
# 示例 1: 执行字符串代码块
code print(Hello, world!)
exec(code)# 示例 2: 指定全局和局部命名空间
globals_dict {x: 5}
locals_dict {}
code y x**2
exec(code, globals_dict, locals_dict)
print(locals_dict[y]) # 输出: 25# 示例 3: 执行代码对象
source_code
def greet(name):print(fHello, {name}!)
greet(Alice)code_obj compile(source_code, string, exec)
exec(code_obj)
x 10expr
z 30
sum x y z
print(sum)
def func():y 20exec(expr)exec(expr, {x: 1, y: 2})exec(expr, {x: 1, y: 2}, {y: 3, z: 4})func()‘’
60
33
34
‘
在expr语句中有三个变量x,y,z,其中z值已给定我们可以在exec()函数外指定x,y的值也可以在exec()函数中以字典的形式指定x,y的值。在最后的语句中我们给出了x,y,z的值并且y值重复exec()函数接收后面一个y值且z值传递不起作用因此输出结果为34. ascii()
ascii(object) 与 repr() 类似返回一个字符串表示对象的可打印 ASCII 码形式。非 ASCII 字符会用 \x、\u 和 \U 进行转义。
它的语法非常简单ascii(object) 直接传入对象即可对于对象中没 ascii 码的内容会用 \x、\u 和 \U 进行转义
ascii(123)
# 123ascii(盖若)
# \\u76d6\\u82e5Languages [pythØn,C,Go]
ascii(Languages)
# [pyth\\xd8n, C, Go]# 字符
c G# ASCII 码
a 99print(c, 的ASCII 码为, ord(c))
print(a, 对应的字符为, chr(a))G 的ASCII 码为 71
99 对应的字符为 cASCII编码是1个字节而Unicode编码通常是2个字节。
字母A用ASCII编码是十进制的65二进制的01000001而在Unicode中只需要在前面补0即为00000000 01000001。
新的问题如果统一成Unicode编码乱码问题从此消失了。但是如果你写的文本基本上全部是英文的话用Unicode编码比ASCII编码需要多一倍的存储空间在存储和传输上就十分不划算。
UTF-8 的编码规对于单字节的符号字节的第一位设为0后面7位为这个符号的 Unicode 码。因此对于英语字母UTF-8 编码和 ASCII 码是相同的。
ord()和chr()
ord() 是将单个字符转 Unicode 码点chr() 将 Unicode 码点转为字符 它们两个互为逆函数。
ord(c)给定一个表示一个 Unicode 字符的字符串返回一个表示该字符的 Unicode 码点的整数。例如 ord(a) 返回整数 97 ord(€) 欧元符号返回 8364 。chr(i)返回表示 Unicode 码位为整数 i 的字符的字符串。例如chr(97) 返回字符串 achr(8364) 返回字符串 €。这是 ord() 的逆函数。实参的合法范围是 0 到 1,114,11116 进制表示是 0x10FFFF。如果 i 超过这个范围会触发 ValueError 异常。ord(c)c 为一个字符串返回一个整数这个整数为 Unicode 码位编号chr(i)i 一个整数有上述范围限制返回码位编号为这个整数的 Unicode 字符串
ord(a)
# 97
ord(¥) # 人民币符号
# 165
ord(美国) # 多个字符
# TypeError: ord() expected a character, but string of length 2 foundchr(97)
# a
chr(165)
# ¥
chr(1_114_112) # 大于 1_114_111
# ValueError: chr() arg not in range(0x110000) bin()
将整数转变为以“0b”前缀的二进制字符串。结果是一个合法的 Python 表达式。如果 i 不是 Python 的 int 对象它必须定义 __index__() 方法以便返回整数值。如果未指定整数则会引发TypeError异常突出显示无法解释为整数的类型。
bin(3)
# 0b11bin(-10)
# -0b1010
若要控制是否显示前缀“0b”可以采用以下两种方案
format(14, #b), format(14, b)
# (0b1110, 1110)f{14:#b}, f{14:b}
# (0b1110, 1110)
__index()__
__index()__类似于__str()__方法__str()__输出对象的字符串表示__index()__方法输出对象的整数表示可以自定义对象的 __index()__ 方法
class Quantity:apple 1orange 2grapes 2def __index__(self):return self.apple self.orange self.grapesbin(Quantity())
# 0b101
在这里我们向 bin() 方法发送了一个 Quantity 类的对象。即使对象数量不是整数 bin() 方法也不会引发错误。这是因为我们实现了返回整数水果数量之和的 __index__() 方法。然后将该整数提供给 bin() 方法。
hex()
hex() 用于将10进制整数转换成16进制以「0x」为前缀字符串形式表示。它接受的是一个十进制的数字如果参数不是 Python int 对象则必须定义返回整数的 __index__() 方法。
hex() 函数接受单个参数。
hex(number, /)
参数是一个整数int 对象或必须定义返回整数的 __index__() 特殊方法。
它将整数转换为字符串形式的相应十六进制数并返回。返回的十六进制字符串以前缀「0x」开头表示其为十六进制形式。
如果要获取浮点数的十六进制字符串形式请使用 float.hex() 方法。
hex(255)
# 0xffhex(-42)
# -0x2ahex(12648430)
# ‘0xc0ffee%#x % 255, %x % 255, %X % 255
# (0xff, ff, FF)format(255, #x), format(255, x), format(255, X)
# (0xff, ff, FF)f{255:#x}, f{255:x}, f{255:X}
# (0xff, ff, FF)
oct()
内置函数 oct() 将一个整数转变为一个前缀为「0o」的八进制字符串。必须传入一个整数。
语法为 oct(x)参数
整数二进制、十进制或十六进制如果 x 不是 Python 的 int 对象那它需要定义 __index__() 方法返回一个整数。
oct(8)
# 0o10oct(-56)
# -0o70oct(0b101)
# 0o5oct(0XA)
# 0o12
class Person:age 23def __index__(self):return self.agedef __int__(self):return self.ageperson Person()
print(The oct is:, oct(person))
# The oct is: 0o27Person 类实现了 __index__() 和 __int__()因此我们可以此对象上使用 oct()。
注意为了兼容性推荐 __index__() 和 __int__() 输出结果。
若要将整数转换为八进制字符串并可选择是否带有“0o”前缀可采用如下方法
%#o % 10, %o % 10
# (0o12, 12)
format(10, #o), format(10, o)
# (0o12, 12)
f{10:#o}, f{10:o}
# (0o12, 12) int()
内置函数 int() 是构造方法它可以将数字或字符串转换为整型数字。它还可以通过 base 参数可以转化指定进制的数字。
int() 有两种使用形式分别是
int([x]) - integer
int(x, base10) - integer
它们都会返回一个基于数字或字符串 x 构造的整数对象或者在未给出参数时返回 0。
在第一种情况下可以传入一个 字符, 类字节对象bytes-like object或者一个实数第二种情况可以传入一个 base 变量来指定返回数字的进制默认为 10是我们日常使用的 10 进制。
如果 x
定义了 __int__()int(x) 将返回 x.__int__() 定义的值。定义了 __index__()它将返回 x.__index__() 定义的的值。定义了 __trunc__()它将返回 x.__trunc__() 的值。
以上几个如果定义了两种及三种会按以上顺序依次返回排在前边的值。
对于浮点数它将截断小数位舍去所有小数位上的数字。
如果 x 不是数字或者有 base 参数x 必须是字符串、bytes、表示进制为 base 的 整数字面值 的 bytearray 实例。该文字前可以有 或 - 中间不能有空格前后可以有空格。
一个进制为 n 的数字包含 0 到 n-1 的数其中 a 到 z 或 A 到 Z 表示 10 到 35。默认的 base 为 10 允许的进制有 0、2-36。
2、8、16 进制的数字可以在代码中用 0b/0B 、 0o/0O 、 0x/0X 前缀来表示。进制为 0 将安照代码的字面量来精确解释最后的结果会是 2、8、10、16 进制中的一个。所以 int(010, 0) 是非法的但 int(010) 和 int(010, 8) 是合法的。
默认为 10 进制
# integer
int(123)
# float
int(123.23)
# string
int(123)# 以上均输出
# 123# 字符中可包含分组下划线
int(323_133)
# 323133
用于十进制、八进制和十六进制
# 二进制 binary 0b or 0B
int(1010, 2)
int(0b1010, 2)
# 八进制 octal 0o or 0O
int(12, 8)
int(0o12, 8)
# 十六进制 hexadecimal
int(A, 16)
int(0xA, 16)# 以上均输出
# 10
__int()__
在内部, int() 作为方法可以调用对象的 __int__() 方法。因此即使对象不是个数字也可以将对象转换为整数对象。可以通过重写类的 __index__() 和 __int__() 方法返回一个数字。
这两个方法返回的值应该与较早版本的 Python 使用的 __int__() 相同而较新版本使用的是 __index__() 方法。
class Person:age 23def __index__(self):return self.agedef __int__(self):return self.ageperson Person()
int(person)
# 23
如果无法转换则抛出 ValueError 异常
try:five fiveprint(int(five))
except ValueError as e:print(e)# invalid literal for int() with base 10: five bool()
bool() 函数的作用是使用标准的真值测试过程将值转换为布尔值True 或 False
class bool([x]) 向 bool() 传递值不是强制性的可以不传值。如果不传递值 bool() 将返回 False。通常情况下只接受一个参数值。
bool() 将返回
False 不值或者假值True 值为真值
Python中的真假值
在 Python 中以下值被视为 假值
NoneFalse任何数字类型的零例如00.00j空序列例如 (), [], 空映射例如 {}类的对象特殊方法 __bool__() 返回 False 或是定义了 __len__() 方法且返回 0
除这些值外的所有其他值均视为真。
test []
print(test,is,bool(test))test [0]
print(test,is,bool(test))test 0.0
print(test,is,bool(test))test None
print(test,is,bool(test))test True
print(test,is,bool(test))test Easy string
print(test,is,bool(test))
[] is False
[0] is True
0.0 is False
None is False
True is True
Easy string is True__bool()__
__bool()__与前面的__str()__和__index()__类似定义了对象的布尔表示可以自定义对象的表示
class Student(object):def __init__(self, name, age):self.name nameself.age age# 如果是成年为 Truedef __bool__(self):return self.age 18me Student(小明, 16)
bool(me)
# Falsehim Student(大明, 18)
bool(him)
# True# 用于逻辑判断
if Student(大明, 18):print(成年人)
else:print(未成年人)# 成年人
complex()
complex() 用于创建一个复数对象。可以传入一个在加减号周围无空格的字符串或者两个数字来代表复数的实部和虚部。
有两种参入方法
complex(x:str)
complex(real0, imag0)
返回值为 real imag*1j 的复数或将字符串或数字转换为复数。有两种传参方法。
第一种参数形式
如果第一个形参是字符串则它被解释为一个复数并且函数调用时必须没有第二个形参。
对于一个普通 Python 对象 xcomplex(x) 会委托给 x.__complex__()。 如果 __complex__() 未定义则将回退至 __float__()。 如果 __float__() 未定义则将回退至 __index__()。
注意当从字符串转换时字符串在 或 - 的周围必须不能有空格。
例如 complex(12j) 是合法的但 complex(1 2j) 会触发 ValueError 异常。
第二种参数形式
第二个形参不能是字符串。每个实参都可以是任意的数值类型包括复数。如果省略了 imag则默认值为零构造函数会像 int 和 float 一样进行数值转换。如果两个实参都省略则返回 0j。
complex(1-2j)
# (1-2j)complex(-2j)
# (-0-2j)foo complex(1, 2)
foo
# (12j)foo.conjugate()
# (1-2j)foo.real # 1.0
foo.imag # 2.0 byte()
bytes() 可以生成字节序列又叫字节串字节序列是一个不可变序列包含范围为 0 x 256 的整数bytes 是 bytearray 的不可变版本——带有同样不改变序列的方法支持同样的索引、切片操作。因此构造函数的实参和 bytearray() 相同。
语法构成是
class bytes([source[, encoding[, errors]]]) 它是一个类可以初始化生成一个字节序列对象。
接受三个可选参数
source用于初始化字节串的源数据encoding如果 source 是字符串则可指定字符串的编码errors如果 source 是字符串则编码转换失败时要采取的操作
source 参数可以通过以下方式初始化字节数组
bytes(iterable_of_ints) - bytes创建一个大小等于 iterable 数量的数组并初始化为 iterable 元素必须是 0x256 之间整数的 iterablebytes(string, encoding[, errors]) - bytes将字符串转换为字节串还必须提供编码和可选错误处理见 str.encode()bytes(bytes_or_buffer) - bytes_or_buffer 的不可变副本传入一个 Object对象的只读缓冲区将用于初始化字节数组bytes(int) - 长度为 int 的初始化\x00字节对象bytes() - 空的 bytes 对象
总结可以从以下内容构造一个不变的字节数组
从 range(256) 中迭代出使用指定编码进行编码的文本字符串实现缓冲区API的任何对象整数
# 限制为 0 x 256
bytes(10) # 指定长度的以零值填充的 bytes 对象
# b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00bytes(range(20)) # 通过由整数组成的可迭代对象
# b\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b...obj (1, 2)
bytes(obj) # 通过缓冲区协议复制现有的二进制数据
# b\x01\x02bytes(hello, utf-8)
# bhello
bytearray()
bytearray()返回一个新的 bytes 数组。 bytearray 类是一个可变序列包含范围为 0 x 256 的整数。它有可变序列大部分常见的方法见 可变序列类型 的描述同时有 bytes 类型的大部分方法参见 bytes 和 bytearray 操作。
语法
class bytearray([source[, encoding[, errors]]])
可选形参 source 可以用不同的方式来初始化数组
如果是一个 string您必须提供 encoding 参数errors 参数仍是可选的bytearray() 会使用 str.encode() 方法来将 string 转变成 bytes。如果是一个 integer会初始化大小为该数字的数组并使用 null 字节填充。如果是一个遵循 缓冲区接口 的对象该对象的只读缓冲区将被用来初始化字节数组。如果是一个 iterable 可迭代对象它的元素的范围必须是 0 x 256 的整数它会被用作数组的初始内容。如果没有实参则创建大小为 0 的数组。
bytearray() # 创建一个空实例
# bytearray(b)bytearray(10) # 创建一个指定长度的以零值填充的实例
# bytearray(b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)bytearray(range(20)) # 通过由整数组成的可迭代对象
bytearray(b\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b...)bytearray(bHi!) # 通过缓冲区协议复制现有的二进制数据
# bytearray(bHi!) classmethod() 和staticmethod()
内置函数 classmethod() 是一个装饰器它可以将一个方法封装为一个类的方法。修饰符对应的函数不需要实例化不需要 self 参数但第一个参数需要是表示自身类的 cls 参数可以来调用类的属性类的方法实例化对象等。
内置函数 staticmethod() 是一个装饰器它可以将一个方法封装为一个静态方法该方法不强制要求传递参数。
语法为
classmethod(function) - method
# or
classmethod
def func(cls, args...):passstaticmethod(function) - method
# or
staticmethod
def func(cls, args...):pass
将函数转换为类方法。类方法接收类一般作 cls作为隐式第一个参数就像实例方法接收实例self一样。staticmethod 将方法转换为静态方法。静态方法不会接收隐式的第一个参数。 要声明类方法、静态方法请使用以下习惯用法
class C:classmethoddef f(cls, arg1, arg2, ...):…class C:staticmethoddef f(cls, arg1, arg2, ...):...
类方法可以在类例如 C.f()或实例例如 C().f()使用。实例被忽略但其类除外。 如果为派生类调用类方法则派生类对象将作为隐含的第一个参数传递。
静态方法既可以由类中调用如 C.f()也可以由实例中调用如C().f()。此外还可以作为普通的函数进行调用如 f()。
类方法不同于 C 或 Java 静态方法。如果您想要静态方法可以使用内置的 staticmethod。
像所有装饰器一样也可以像常规函数一样调用 staticmethod 并对其结果执行某些操作。比如某些情况下需要从类主体引用函数并且您希望避免自动转换为实例方法。对于这些情况请使用此语法:
def regular_function():...class C:method staticmethod(regular_function)
无论何时通过将工厂方法实现为类方法来派生类它都可以确保正确创建派生类的实例。
您可以为上面的示例创建一个静态方法但它创建的对象将始终被硬编码为基类。
但是当您使用类方法时它会创建派生类的正确实例。
from datetime import date# random Person
class Person:def __init__(self, name, age):self.name nameself.age agestaticmethoddef fromFathersAge(name, fatherAge, fatherPersonAgeDiff):return Person(name, date.today().year - fatherAge fatherPersonAgeDiff)classmethoddef fromBirthYear(cls, name, birthYear):return cls(name, date.today().year - birthYear)def display(self):print(self.name s age is: str(self.age))class Man(Person):sex Maleman Man.fromBirthYear(John, 1985)
print(isinstance(man, Man))man1 Man.fromFathersAge(John, 1965, 20)
print(isinstance(man1, Man))
True
False在这里使用静态方法创建类实例需要我们在创建过程中硬编码实例类型。这显然会给人与人之间的继承带来问题。
fromFathersAge 方法不返回 Man 对象而是返回其基类 Person 的对象。
这违反了 OOP 范式。将类方法用作 fromBirthYear 可以确保代码的 OOP 性因为它将第一个参数作为类本身并调用其工厂方法。
静态方法和类方法的区别在于
静态方法对类一无所知只处理自己的参数。类方法与类一起工作因为它的参数始终是类本身。
property()
内置函数类 property() 一般以装饰器 property 的形式出现我们可以使用它来创建只读属性会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用这样可以防止属性被修改。同时还可以指定获取、设置、删除的方法。
语法如下
class property(fgetNone, fsetNone, fdelNone, docNone)参数
fget用于获取属性值的函数fset用于设置属性值的函数fdel用于删除属性的函数docdocstring文档字符串
其中如果 doc 参数给出doc 将成为该 property 属性的文档字符串。 否则该 property 将拷贝 fget 的文档字符串如果存在。 这令使用 property() 作为 decorator 来创建只读的特征属性可以很容易地实现:
class Parrot:def __init__(self):self._voltage 100000propertydef voltage(self):Get the current voltage.return self._voltage
以上 property 装饰器会将 voltage() 方法转化为一个具有相同名称的只读属性的 getter并将 voltage 的文档字符串设置为 Get the current voltage.
特征属性对象具有 getter, setter 以及 deleter 方法它们可用作装饰器来创建该特征属性的副本并将相应的访问函数设为所装饰的函数。 这最好是用一个例子来解释:
class C:def __init__(self):self._x Nonepropertydef x(self):Im the x property.return self._xx.setterdef x(self, value):self._x valuex.deleterdef x(self):del self._x
class Shijin:def __init__(self, jin, liang):self.total_liang jin * 10 liang# 获取斤propertydef jin(self):return self.total_liang // 10# 获取和设置两propertydef liang(self):return self.total_liang % 10liang.setterdef liang(self, new_liang):self.total_liang 10 * self.jin new_liangdef __repr__(self):return {}斤{}两.format(self.jin, self.liang)jiaozi Shijin(3, 2)jiaozi
# 3斤2两jiaozi.liang 4
jiaozi
# 3斤4两jiaozi.liang 6jiaozi
# 4斤0两jiaozi.jin 10
# AttributeError: cant set attribute jinjiaozi.jin
# 4 id()
id(object) 返回对象的“标识值”。该值是一个整数在此对象的生命周期中保证是唯一且恒定的。两个生命期不重叠的对象可能具有相同的 id() 值。在 CPython 实现中这就是内存中对象的地址。对象的 id 对于 Python 缓存这些变量的值很有用。这种使用 id() 检索缓存值的机制使 Python 的性能更好这在多个变量引用同一对象的情况下也有帮助。注本页的代码 id 结果不会与你执行相同代码时相同。
语法为 id(object)由于在 Python 一切皆为对象所有的对象都可以传入 id() 中。示例
a 1
id(a)
# 140232072763696id(1)
# 140232072763696id(lambda x: x1)
# 140359443164176def hello():print(hello!)id(hello)
# 140231834272240# 未定义的名称
id(test)
# NameError: name test is not defined
上例中a 与 1 的 id() 返回值相同则证明它们在内存中的地址memory address of the Python object相同。这个地址只在一个生命周期内是相同的如果重启解释器交互窗口或者重新执行则会改变。
对于可变对象内容即使相同它们的内存地址也不同。请记住缓存只能在不可变的 Python 对象上工作如整数、字符串和浮点。元组、列表等是可变对象因此缓存在这里不起作用
class Student:data 0e1 Student()
e2 Student()print(id(e1))
print(id(e2))# 140231806582208
# 140231806582688
上边说了如果对象的内容相同Python 不会新开辟空间存储而是指向同一个对象下边的两个对象 id() 是相同的
判断两个对象是否相等可以用 is 操作
a is b
# True它就等于
id(a) id(b)
两个对象如何才能相等要比我们想象的复杂很多但核心的方法是重写 __eq__ 方法这个方法返回 True则表示两个对象相等否则就不相等。相反的如果两个对象不相等则重写 __ne__ 方法。
默认情况下如果你没有实现这个方法则使用父类(object)的方法。父类的方法比较是的两个对象的ID(可以通过id方法获取对象ID)也就是说如果对象的ID相等则两个对象也就相等。因此我们可以得知默认情况下对象只和自己相等。
enumerate()
enumerate() 方法将计数器添加到 iterable 每个元素连同计数或者称为索引组成元组并返回它枚举对象 enumerate object。
enumerate() 的语法为
enumerate(iterable, start0)
enumerate() 方法采用两个参数
iterable - 可迭代的序列start (可选) - 从这个数字开始计数默认为 0
返回
方法将计数器添加到 iterable 并返回它。返回的对象是枚举对象。可以分别使用 list() 和 tuple() 方法将枚举对象转换为 list 和 tuple。例如
seasons [Spring, Summer, Fall, Winter]
list(enumerate(seasons))
# [(0, Spring), (1, Summer), (2, Fall), (3, Winter)]
list(enumerate(seasons, start1))
# [(1, Spring), (2, Summer), (3, Fall), (4, Winter)]
等价于:
def enumerate(sequence, start0):n startfor elem in sequence:yield n, elemn 1
一般在 for 循环中为列表增加索引方便让这些索引数字介入计算
l [Alice, Bob, Charlie]# 一般的循环
for name in l:print(name)
# Alice
# Bob
# Charlie# 可以按索引编号和元素的顺序获取
for i, name in enumerate(l):print(i, name)
# 0 Alice
# 1 Bob
# 2 Charlie 上例那样默认情况下enumerate() 函数的索引从 0 开始。如果想要从 0 以外的数值开始则对 enumerate() 函数的第二参数指定任意的开始数值。如从 1 开始时
for i, name in enumerate(l, 1):print(i, name)
# 1 Alice
# 2 Bob
# 3 Charlie
想制作序列号的字符串时很方便。比起从 1 开始 i1用 enumerate() 函数的第二参数指定开始数值更智能。
for i, name in enumerate(l, 1):print({:03}_{}.format(i, name))
# 001_Alice
# 002_Bob
# 003_Charlie
在 enumerate() 函数中没有指定增量step的参数但是可以实现如下
step 3
for i, name in enumerate(l):print(i * step, name)
# 0 Alice
# 3 Bob
# 6 Charlie hash()
内置函数 hash() 可以返回对象的哈希值。哈希值又称散列值它是一个固定大小的整数用于标识对象的特定值。hash() 又称散列算法、哈希函数是一种从任何一种数据中创建小的数字“指纹”的方法。
hash(你好)
# 2439288928012809752hash(123)
# 123hash(123.0)
# 123hash(range(2))
# 7853416581674910768hash((1, 2))
# -3550055125485641917hash([1, 2])
# TypeError: unhashable type: list
如果对象实现了自己的 __hash__() 方法hash() 根据机器的字长来截断返回值。自己要实现 hash 功能可以在对象中来重写 __hash__() 来自定义 hash 值。
自己定义的 __hash__() 要返回一个整数必须同时实现 __eq__() 和 __hash__()下面是正确是正确的的例子
class Person:def __init__(self, age, name):self.age ageself.name namedef __eq__(self, other):return self.age other.age and self.name other.namedef __hash__(self):print(The hash is:)return hash((self.age, self.name))person Person(23, Adam)
hash(person)
# -1253368434537217793
如无必要对象不必自己实现 __eq__() 方法因为它是默认为所有对象创建的。 memoryview()
内置函数 memoryview() 返回给定参数的内存查看对象memory view。memoryview 对象允许 Python 代码访问支持缓冲区协议的对象的内部数据而无需复制。
语法
class memoryview(object) 创建一个引用 obj 的 memoryview。obj 必须支持缓冲协议。支持缓冲区协议的内置对象包括字节bytes和字节数组bytearray。
v memoryview(babcefg)
v[1]
# 98
v[-1]
# 103
v[1:4]
# memory at 0x7f3ddc9f4350
bytes(v[1:4])
# bbce
iter()
内置函数 iter() 用来生成迭代器它可以将字符串、列表、元组等序列转换为可迭代器供 for 循环、next() 等进行迭代操作。 iter的语法有两种
iter(iterable) - iterator
iter(callable, sentinel) - iterator 从对象中获取迭代器。在第一种形式中参数必须提供自己的迭代器或者是一个序列。
在第二种形式中将调用 callable直到它返回 sentinel。
如果只传入一个参数就按第一种解释如果传入两个就按第二种方法解释。
参数分别是
第一种方法 iterable可迭代对象或者一个序列如列表、字符串、字典等直接将这个可迭代对象转为迭代器。或者它必须支持 sequence 协议__getitem__() 方法整数参数从0开始否则引发 TypeError。第二种方法 callable可调用对象一个函数的名称。每次调用其 __next__() 方法不带任何参数如果返回的值等于 sentinel则将引发 StopIteration否则将返回该值。见示例中关于读取文件有用法。sentinel哨兵见 object() 中相关概念的介绍当迭代值为此值时抛出 StopIteration。
返回一个迭代器对象。
对于一个对象要支持 iter() 函数需要在内部实现 __iter__() 特殊方法。
from functools import partial
with open(mydata.db, rb) as f:for block in iter(partial(f.read, 64), b):process_block(block)
由于 callable 不能带任何参数先用偏函数处理。以上代码当数据读取为空时引发 StopIteration在 for 是停止。
reversed()
内置函数 reversed() 会返回给定序列的反向迭代器如果需要查看返回的这个迭代器的内容需要迭代输出或者转换为列表、元组等数据类型。
语法是
reversed(seq)
seq 可以是
tuple, string, list 或 range 等具有 __reversed__() 方法的对象支持该序列协议具有从 0 开始的整数类型参数的 __len__() 方法和 __getitem__() 方法。
可以对任意实现了 __reverse__() 特殊方法的对应使用 reversed()。
class Vowels:vowels [a, e, i, o, u]def __reversed__(self):return reversed(self.vowels)v Vowels()
list(reversed(v))
# [u, o, i, e, a]
next()
可以从迭代器中检索下一项如果给定默认值则在迭代器耗尽时返回此默认值否则将引发 StopIteration 异常
语法是
next(iterator[, default])
参数说明
iterator必须它必须是一个迭代器或者生成器可由 iter() 将序列转换而来default可选如果迭代器的元素耗尽消费完则返回此值否则引发 StopIteration 异常
作用是从迭代器返回下一项。如果给定了默认值并且迭代器已耗尽则返回它而不是引发 StopIteration。
it iter([1, 2, 3])
while True:try:x next(it)print(x)except StopIteration:print(Over)break round()
round() 返数字舍入到小数点后指定位精度的值。 如果不指定小数位精度则返回最接近输入值的整数。这是一个数字修约操作。数值修约是指在进行具体的数字运算前按照一定的规则确定一致的位数然后舍去某些数字后面多余的尾数的过程。
语法为 round(number, ndigitsNone)
期中 ndigits 是一个将数字舍入到给定的小数精度。如果省略 ndigits 或无 ndigits则返回值为整数。否则返回值的类型与数字相同。ndigits 可能是负的。
对于支持 round() 方法的内置类型结果值会舍入至最接近的 10 的负 ndigits 次幂的倍数如果与两个倍数同样接近则选用偶数。因此round(0.5) 和 round(-0.5) 均得出 0 而 round(1.5) 则为 2。ndigits 可为任意整数值正数、零或负数。如果省略了 ndigits 或为 None 则返回值将为整数。否则返回值与 number 的类型相同。
对于一般的 Python 对象 number, round 将委托给 number.__round__可以类中实现此特殊方法。
对浮点数执行 round() 的行为可能会令人惊讶例如round(2.675, 2) 将给出 2.67 而不是期望的 2.68。 这不算是程序错误这一结果是由于大多数十进制小数实际上都不能以浮点数精确地表示。例如当十进制 2.675转换为二进制浮点数时它再次被二进制近似值替换其精确值为
2.67499999999998223643160599749535322183310546875
因此四舍五入为 2.67而不是 2.68。
浮点数在计算机硬件中表示为以 2 为基数二进制的小数。由于这个 0.1 无法精确表示 1/10 的值而这个 0.3 也无法精确表示 3/10 的值使用 round() 函数进行预先舍入也是没用的:
虽然这些小数无法精确表示其所要代表的实际值round() 函数还是可以用来“事后舍入”使得实际的结果值可以做相互比较:
round(.1 .1 .1, 10) round(.3, 10)
# True
如果你需要比较高的精度考虑使用 decimal 模块它设计用于浮点运算
from decimal import Decimal# normal float
num 2.675
round(num, 2)
# 2.67# 使用 decimal.Decimal (将浮点作为字符串传递以提高精度)
num Decimal(2.675)
round(num, 2)
# 2.68
可以自己定义一个方法。一种方法是将移位值加上0.5然后用 math.floor()地板除。原理是
如果移位值的第一位小数位数小于5则加 0.5 不会改变移位值的整数部分因此下限等于整数部分如果小数点后的第一位大于或等于5则加0.5将使移位值的整数部分增加1因此下限等于这个较大的整数
简单说就是利用了 int 直接截断的特性测试如下以保留两个小数为例
int(0.115*1000.5)/100
# 0.12int(0.125*1000.5)/100
# 0.13
import mathdef round_half_up(n, decimals0):multiplier 10 ** decimalsreturn math.floor(n*multiplier 0.5) / multiplierround_half_up(0.625, 2)
# 0.63
还有一种办法是用 decimal 模块的 quantize 方法强烈推荐
from decimal import DecimalDecimal(0.625).quantize(Decimal(0.01), rounding ROUND_HALF_UP)
# Decimal(0.63)
其他方法
import decimalDecimal(1.115).quantize(Decimal(0.00), roundingdecimal.ROUND_HALF_UP)
# Decimal(1.12)Decimal(0.125).quantize(Decimal(0.00), roundingdecimal.ROUND_HALF_UP)
# Decimal(0.13)
可以再将 Decimal 对象再转为浮点型。
from decimal import Decimaldef round_half_up(n, d):assert d 1, d 不能小于1assert type(d) int, d 必须为整型num Decimal(str(n))num num.quantize(Decimal(0.0*d),roundingROUND_HALF_UP)return float(num) if d1 else int(num)round_half_up(0.625, 2)
# 0.63round_half_up(3.14, 1)
# 3
除非对精确度没什么要求否则尽量避开用round()函数。近似计算我们还有其他的选择
使用math模块中的一些函数比如 math.ceiling天花板除法python 自带整除//还有 div 函数。字符串格式化可以做截断使用例如 %.2f % value保留两位小数并变成字符串当然对浮点数精度要求如果很高的话请用 decimal 模块。
abs()
返回一个数的绝对值常用在数学计算中
语法形式是 abs(x) 必传且只能传入一个参数这个参数必须是一个数字。它可以接受的数据包括
整型 integer浮点型 floating number复数 complex number任何实现了 __abs__() 的对象
返回一个数的绝对值。具体情况下
整型 integer返回整数绝对值浮点型 floating number返回浮点绝对值复数 complex number复数的模magnitude
注复数的模magnitude是该复数与共轭复数的乘积的正平方根就是 (a^2b^2) 开平方根。
# 整数的情况
abs(10)
# 10
abs(-10)
# 10# 浮点型的情况
abs(-3.14)
# 3.14# 复数的情况
complex1 (5 - 6j)
abs(complex1)
# 7.810249675906654complex2 (3 - 4j)
abs(complex2)
# 5.0abs(1j)
#1.0
构建新的数据对象时可以通过实现 __abs__() 让内置的 abs 操作数据。
class Student(object):这是一个学生类def __init__(self, name):self.name namedef __abs__(self):print(f{self.name} 绝对棒)lily Student(lily)abs(lily)
# lily 绝对棒
divmod()
内置函数 divmod() 返回这两个数字的商和余数模组成的元组即 (x//y, x%y)。
语法非常简单直接传入两个要计算的数字
divmod(x, y, /)
他们不能为负数y 不能为 0。
以两个非复数数字为参数在作整数除法时返回商和余数。
若操作数为混合类型则适用二进制算术运算符的规则。对于整数而言结果与 (a // b, a % b) 相同。
divmod(10, 3)
# (3, 1)
divmod(10, -1)
# (-10, 0)
divmod(10, 0.1)
# (99.0, 0.09999999999999945)
divmod(10, 0)
# ZeroDivisionError: integer division or modulo by zero
divmod(0, 10)
# (0, 0)
pow()
内置函数 pow() 可以求一个数的 n 次幂即返回 x^yx 的 y 次方 的值。
语法如下
pow(base, exp, modNone)返回 base**exp 的值如果 mod 有传入则返回 base**exp % mod 先求 n 次幂再取模。
某些类型例如 int在使用三参数形式调用时能够使用更高效的算法。
参数必须是数字类型。对于混合操作数类型二进制算术运算符的强制规则适用。
对于整型操作数结果的类型与操作数的类型相同强制后除非第二个参数为负在这种情况下所有参数都转换为float并传递一个float结果。例如pow102返回100但pow10-2返回0.01。
对于int或float类型的负基和非整数指数将给出一个复杂的结果。例如pow(-90.5) 返回一个接近3j的值。
对于 int 操作数 base 和 exp如果给出 mod则 mod 必须为整数类型并且 mod 必须不为零。 如果给出 mod 并且 exp 为负值则 base 必须相对于 mod 不可整除。 在这种情况下将会返回 pow(inv_base, -exp, mod)其中 inv_base 为 base 的倒数对 mod 取余。
下面的例子是 38 的倒数对 97 取余:
pow(38, -1, mod97)
# 2323 * 38 % 97 1
# True
它与 ** 操作以及 math.pow() 的区别为
pow() 相同于 ** 操作math.pow() 计算的结果是浮点math.pow() 不支持第三个参数进行取模
可以对对象实现 __pow__(), __rpow__() or __ipow__() 方法来支持 power 操作。