Tips20:Python 内置函数
在此篇教程中,我们将借助示例来了解 Python 中的一些内置函数 。
abs(),any(),all(),ascii(),bin(),bool(),bytearray(),callable(),bytes(),chr(),compile(),classmethod(),complex(),delattr(),dict(),dir(),divmod(),
enumerate(),staticmethod(),filter(),eval(),float(),format(),frozenset(),getattr(),globals(),exec(),hasattr(),help(),hex(),hash(),input(),id(),isinstance(),
int(),issubclass(),iter(),list(),locals(),len(),max(),min(),map(),next(),memoryview(),object(),oct(),ord(),open(),pow(),print(),
property(),range(),repr(),reversed(),round(),set(),setattr(),slice(),sorted(),str(),sum(),tuple(),type(),vars(),zip(),__import__(),super()……etc
enumerate()
函数向迭代器、序列中添加一个计数器并返回它(为枚举对象)。
例如
languages = ['Python', 'C++', 'Matlab']
enumerate_prime = enumerate(languages)
# 将枚举对象转换为列表
print(list(enumerate_prime))
# 输出: [(0, 'Python'), (1, 'C++'), (2, 'Matlab')]
enumerate() 语法
enumerate()
的语法是:
enumerate(iterable, start=0)
enumerate() 参数
enumerate()
函数接受两个参数:
- iterable – 支持迭代的序列、迭代器或对象
- start (可选参数) –
enumerate()
从这个数字开始计数,如果省略 start ,则取0
作为start
。
enumerate() 返回值
enumerate()
函数将计数器添加到迭代器、序列中并返回它,返回的对象是一个枚举对象。
你可以分别使用 list() 和 tuple() 内置函数将枚举对象转换为列表和元组。
✎示例1-enumerate() 如何工作?
grocery = ['bread', 'milk', 'butter']
enumerateGrocery = enumerate(grocery)
print(type(enumerateGrocery))
# 转换为列表
print(list(enumerateGrocery))
# 更改默认计数器 0->10
enumerateGrocery = enumerate(grocery, 10)
print(list(enumerateGrocery))
▧ 输出
<class 'enumerate'> [(0, 'bread'), (1, 'milk'), (2, 'butter')] [(10, 'bread'), (11, 'milk'), (12, 'butter')]
✎示例2-for语句循环遍历 Enumerate 对象
grocery = ['bread', 'milk', 'butter']
for item in enumerate(grocery):
print(item)
print('\n')
for count, item in enumerate(grocery):
print(count, item)
print('\n')
# 更改默认的初始值
for count, item in enumerate(grocery, 100):
print(count, item)
▧ 输出
(0, 'bread') (1, 'milk') (2, 'butter') 0 bread 1 milk 2 butter 100 bread 101 milk 102 butter
staticmethod()
函数返回给定函数的静态方法。
例如
class Calculator:
def add_numbers(num1, num2):
return num1 + num2
# 将 add_numbers() 转换为静态方法
Calculator.add_numbers = staticmethod(Calculator.add_numbers)
sum = Calculator.add_numbers(5, 7)
print('Sum:', sum)
# 输出: Sum: 12
staticmethod() 语法
staticmethod()
的语法为:
staticmethod(function)
Note: staticmethod()
被认为是创建静态函数的非 Python 简洁化设计原则,因此,在最新的Python版本中,你可以使用 @staticmethod
装饰器来替换,如下:
@staticmethod
的语法是:
@staticmethod def func(args, ...)
staticmethod() 参数
staticmethod()
函数接受单个参数:
- function – 需要转换为静态方法的函数
staticmethod() 返回值
staticmethod()
为作为参数传递的函数返回一个静态方法。
何为静态方法?
静态方法,很像类方法,是绑定到类而不是它的对象的方法。
它们不需要创建类实例。因此,它们不依赖于对象的状态。
静态方法和类方法的区别在于:
- 静态方法对类一无所知,只处理参数。
- 类方法与类一起使用,因为它的参数始终是类本身。
它们可以被类和它的对象调用,如下:
Class.staticmethodFunc() 甚至 Class().staticmethodFunc()
✎示例 1-使用 staticmethod() 创建静态方法
class Mathematics:
def addNumbers(x, y):
return x + y
# 创建 addNumbers 函数的静态方法
Mathematics.addNumbers = staticmethod(Mathematics.addNumbers)
print('The sum is:', Mathematics.addNumbers(5, 10))
▧ 输出
The sum is: 15
何时使用静态方法?
1. 将实用的程序函数分组到一个类
静态方法的用例有限,因为与类方法或类中的任何其他方法一样,它们无法访问类本身的属性。
但是,当需要一个不访问类的任何属性,但某种意义上可以理解它属于该类的实用的程序函数时,我们使用静态函数。
✎示例 2-创建一个实用的程序函数作为静态方法
class Dates:
def __init__(self, date):
self.date = date
def getDate(self):
return self.date
@staticmethod
def toDashDate(date):
return date.replace(“/”, “-“)
date = Dates("15-12-2016")
dateFromDB = "15/12/2016"
dateWithDash = Dates.toDashDate(dateFromDB)
if(date.getDate() == dateWithDash):
print("等价")
else:
print("不等价")
▧ 输出
等价
在这里,我们有一个 Dates
类,它只适用于带 -
分隔的日期。但是,在我们之前的数据库中,所有日期都以 /
分隔来表示的。
为了将带 /
日期转换为带 -
日期,我们在 Dates
中创建了一个实用的程序函数 toDashDate
。
它是一个静态方法,因为它不需要访问 Dates
本身的任何属性,只需要参数。
我们也可以在类外创建 toDashDate
,但由于它仅适用于日期,因此将其保留在 Dates
类中。
2. 单一实现
当我们不希望类的子类更改/覆盖方法的特定实现时,使用静态方法。
✎示例 3-继承如何与静态方法一起工作?
class Dates:
def __init__(self, date):
self.date = date
def getDate(self):
return self.date
@staticmethod
def toDashDate(date):
return date.replace(“/”, “-“)
class DatesWithSlashes(Dates):
def getDate(self):
return Dates.toDashDate(self.date)
date = Dates("15-12-2016")
dateFromDB = DatesWithSlashes("15/12/2016")
if(date.getDate() == dateFromDB.getDate()):
print("等价")
else:
print("不等价")
▧ 输出
等价
在这里,我们不希望子类 DatesWithSlashes
覆盖静态实用程序的方法 toDashDate
,因为它只有一个用途,即将日期更改为带 -
日期。
通过覆盖子类中的 getDate()
方法,我们可以轻松地使用静态方法来发挥其优势,以便它与 DatesWithSlashes
类一起工作。
filter()
函数从函数返回 True 的迭代器(列表、元组等)中提取元素。
例如
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 如果数字是偶数,则返回True
def check_even(number):
if number % 2 == 0:
return True
return False
# 从数字列表中提取 check_even() 函数返回 True 的元素
even_numbers_iterator = filter(check_even, numbers)
# 转换为列表
even_numbers = list(even_numbers_iterator)
print(even_numbers)
# 输出: [2, 4, 6, 8, 10]
filter() 语法
其语法为:
filter(function, iterable)
filter() 参数
filter()
函数有两个参数:
- function – 一个函数
- iterable – 如集合、列表、元组等的迭代器
filter() 返回值
filter()
函数返回一个迭代器。
Note: 你可以轻松地将迭代器转换为列表、元组、字符串等序列
✎示例 1-filter() 的工作
letters = ['a', 'b', 'd', 'e', 'i', 'j', 'o']
# 一个函数,如果字母是元音则返回 True
def filter_vowels(letter):
vowels = ['a', 'e', 'i', 'o', 'u']
return True if letter in vowels else False
filtered_vowels = filter(filter_vowels, letters)
# 转换为元组
vowels = tuple(filtered_vowels)
print(vowels)
▧ 输出
('a', 'e', 'i', 'o', 'u')
这里,filter()
函数只从 letters
列表中提取元音字母。下面是这段代码的工作原理:
letters
列表的每个元素都传递给filter_vowels()
函数。- 如果
filter_vowels()
返回True
,则提取该元素,否则将其过滤掉。
Note: 也可以使用循环来过滤列表,但是,使用 filter()
函数简单的多。
✎示例 2-在 filter() 内部使用 Lambda 函数
numbers = [1, 2, 3, 4, 5, 6, 7]
# lambda 函数对于偶数返回 True
even_numbers_iterator = filter(lambda x: (x%2 == 0), numbers)
# 转换为 列表(list)
even_numbers = list(even_numbers_iterator)
print(even_numbers)
▧ 输出
[2, 4, 6]
在这里,我们直接在 filter()
内部传递了一个 lambda
函数。
其中 lambda
函数对于偶数返回 True
。因此,filter()
函数返回一个只包含偶数的迭代器。
✎示例 3-在 filter() 内部使用 None 作为函数
# 随机 列表(list)
random_list = [1, 'a', 0, False, True, '0']
filtered_iterator = filter(None, random_list)
# 转换为 列表(list)
filtered_list = list(filtered_iterator)
print(filtered_list)
▧ 输出
[1, 'a', True, '0']
当 None
用作 filter()
函数的第一个参数时,提取所有为真值的元素(如果转换为布尔值则为 True
)。
eval()
函数用来解析传递给该函数的表达式,并在程序中运行其 Python 表达式(即代码)。
例如
number = 9
# eval 执行作为参数传递乘法
square_number = eval(‘number * number’)
print(square_number)
# 输出: 81
eval() 语法
eval()
的语法:
eval(expression, globals=None, locals=None)
eval() 参数
eval()
函数接受三个参数:
- expression – 作为 Python 表达式解析和判断的字符
- globals (可选参数) – 字典
- locals (可选参数)- 映射对象。字典是 Python 中标准和常用的映射类型
globals 与 locals 的使用将在后面内容中进行说明。
eval() 返回值
eval()
函数返回从 expression
计算的结果。
✎示例 1:eval() 工作原理
x = 1
print(eval(‘x + 1’))
▧ 输出
2
此处,eval()
函数计算表达式 x + 1
并使用 print
显示该值。
✎示例 2:演示 eval() 用法的实际示例
# 正方形的周长
def calculatePerimeter(l):
return 4*l
# 正方形的面积
def calculateArea(l):
return l*l
expression = input("输入一个函数表达式: ")
for l in range(1, 5):
if (expression == 'calculatePerimeter(l)'):
print(“如果长度是 “, l, “, 周长 = “, eval(expression))
elif (expression == 'calculateArea(l)'):
print(“如果长度是 “, l, “, 面积 = “, eval(expression))
else:
print('错误的函数')
break
▧ 输出
输入一个函数表达式: calculateArea(l) 如果长度是 1 , 面积 = 1 如果长度是 2 , 面积 = 4 如果长度是 3 , 面积 = 9 如果长度是 4 , 面积 = 16
使用 eval() 时警告
考虑到,你使用 Unix 系统(macOS、Linux 等)的情况下,然后你导入了 os
模块。os
模块提供了一种使用操作系统的功能,例如读取或写入文件。
如果允许用户使用 eval(input())
来输入值的话,用户可能会使用以下命令,更改文件甚至删除所有文件,如:os.system('rm -rf *')
。
如果你在代码中使用 eval(input())
,最好检查一下用户可以使用哪些变量和函数。你可以使用 dir()
函数查看哪些变量和函数可用。
from math import *
print(eval(‘dir()’))
▧ 输出
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'os', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
限制在 eval() 中使用可用的函数和变量
通常情况下,expression中使用的所有可用的函数和变量(eval()的第一个参数)可能都不需要,甚至可能存在安全漏洞。故而需要限制对eval()使用这些函数和变量。可通过将可选的globals和locals参数(字典)传递给eval()函数来实现。
1. 当 globals 和 locals 参数都省略时
如果两个参数都被省略(如我们之前的示例),则expression将在当前作用域中执行。你可以使用以下代码检查可用的变量和函数:
print(eval('dir()')
2. 传递 globals 参数;省略 locals 参数
globals和locals参数(字典)分别用于全局变量和局部变量。如果省略locals字典,则默认为globals字典。意思是,globals将用于全局变量和局部变量。
Note: 你可以分别使用 global() 和 locals() 内置函数在 Python 中检查当前的全局和局部字典。
✎示例 3:将空字典作为 globals 参数传递
from math import *
print(eval(‘dir()’, {}))
# 代码将引发异常
print(eval(‘sqrt(25)’, {}))
▧ 输出
['__builtins__'] Traceback (most recent call last): File "<string>", line 5, in <module> print(eval('sqrt(25)', {})) File "<string>", line 1, in <module> NameError: name 'sqrt' is not defined
以上,如果将空字典作为global传递,则只有__builtins__可用于expression(eval()的第一个参数)。
即使我们在上面的程序中导入了math
模块,expression
也无法访问 math 模块中提供的任何函数。
✎示例 4:使某些函数可用
from math import *
print(eval(‘dir()’, {‘sqrt’: sqrt, ‘pow’: pow}))
▧ 输出
['__builtins__', 'pow', 'sqrt']
在这里,表达式只能使用 sqrt()
和 pow()
函数以及 __builtins__
。
也可以根据需要更改 expression
可用的函数名称:
from math import *
names = {'square_root': sqrt, 'power': pow}
print(eval(‘dir()’, names))
# 在表达式中使用 square_root 替换了原来的 sqrt
print(eval(‘square_root(9)’, names))
▧ 输出
['__builtins__', 'power', 'square_root'] 3.0
在上面的程序中,square_root()
替换使用 sqrt()
计算平方根。故而,尝试直接使用 sqrt()
则会引发错误!
✎示例 5:限制使用内置函数
可以限制在 expression
中使用 __builtins__
如下:
eval(expression, {'__builtins__': None})
3. 传递 globals 和 locals 字典
你可以通过传递locals字典使所需的函数和变量可用。例如:
from math import *
a = 169
print(eval(‘sqrt(a)’, {‘__builtins__’: None}, {‘a’: a, ‘sqrt’: sqrt}))
▧ 输出
13.0
在这个程序中,expression只能有sqrt()函数和变量a。所有其他函数和变量都将不可用。
通过传递 globals
和 locals
字典来限制 eval()
的使用,将使得我们的代码比较安全,特别是当使用用户提供给 eval()
方法的输入时,上面所述的警告。
Note: 有时,即使名称有所限制,eval()
也会不安全。当一个对象及其方法(函数)可以访问时,几乎任何事情都可以做,那么,唯一安全的方法则是验证用户的输入。
float()
函数从数字或字符串返回一个浮点数。
例如
int_number = 25
# 转换为 float
float_number = float(int_number)
print(float_number)
# 输出: 25.0
float() 语法
float()
的语法是:
float([x])
float() 参数
float()
函数接受一个参数:
- x (可选参数) – 需要转换为浮点数的数字或字符串,如果是字符串,则字符串应包含小数点。
参数类型 | 用法 |
---|---|
浮点数 | 用作浮点数 |
整型 | 用作整型 |
字符串 | 必须包含十进制。删除前面和后面的空格;可选使用”+”, “-” 符号;可以包含 NaN , Infinity , inf (小写或大写)。 |
float() 返回值
float()
函数返回:
- 如果传递参数,则等效为浮点数
- 0.0 – 如果没有传递参数
OverflowError
– 如果超出 Python 浮点数范围,则异常
✎示例1-float()如何工作?
# 对于整型
print(float(10))
# 对于浮点型
print(float(11.22))
# 对于字符串浮点数
print(float(“-13.33”))
# 对于带有空格的字符串浮点数
print(float(” -24.45\n”))
# 字符串浮点错误
print(float(“abc”))
▧ 输出
10.0 11.22 -13.33 -24.45 ValueError: could not convert string to float: 'abc'
✎示例2: float() 表示 inf/infinity 和 Nan(不是数字)?
# 对于 NaN
print(float("nan"))
print(float(“NaN”))
# 对于 inf/infinity
print(float("inf"))
print(float("InF"))
print(float(“InFiNiTy”))
print(float("infinity"))
▧ 输出
nan nan inf inf inf inf
format()
函数返回由格式说明符控制的给定值的格式化表示。
例如
value = 45
# 将整数格式化为二进制
binary_value = format(value, ‘b’)
print(binary_value)
# 输出: 101101
format() 语法
其语法为:
format(value[, format_spec])
format() 参数
format()
函数接受两个参数:
- value – 需要格式化的值
- format_spec – 关于格式化值的规范
格式说明符可以采用以下的格式:
[[fill]align][sign][#][0][width][,][.precision][type] where, the options are fill ::= any character align ::= "<" | ">" | "=" | "^" sign ::= "+" | "-" | " " width ::= integer precision ::= integer type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
format() 返回值
format()
函数返回格式说明符指定的给定值的格式化表示
✎示例1: 使用 format() 格式化数字
# d, f 与 b 是类型
# 整型
print(format(123, “d”))
# 浮点参数
print(format(123.4567898, “f”))
# 二进制格式
print(format(12, “b”))
▧ 输出
123 123.456790 1100
✎示例2-带有填充、对齐、符号、宽度、精度和类型的数字格式
# 整型
print(format(1234, “*>+7,d”))
# 浮点数
print(format(123.4567, “^-09.3f”))
▧ 输出
*+1,234 0123.4570
在这里,当格式化整数 1234
时,我们指定了格式化说明符 *>+7,d
。以下为每个选项含义:
*
– 它是填充字符,用于填充格式化后的空格>
– 右对齐选项将输出字符串向右对齐+
– 它是强制数字签名的符号选项(在其左侧有一个符号)7
– 是宽度选项强制数字取最小宽度为 7,其他空格将由填充字符填充,
– 千位运算符在所有千位之间放置一个逗号。d
– 指定数字是整数的是类型选项。
在格式化浮点数 123.4567
时,我们指定了格式说明符 ^-09.3f
。这些含义是:
^
– 它是将输出字符串与剩余空间的中心对齐的居中对齐选项-
– 它是强制仅负数显示符号的符号选项0
– 它是放置在空白处的字符。9
– 是宽度选项,设置数字的最小宽度为9(包括小数点、千位逗号和符号).3
– 将给定浮点数的精度设置为 3 位的精度运算符f
– 指定数字是浮点数的是类型选项。
✎示例3: 通过覆盖 __format__() 使用 format()
# 自定义 __format__() 方法
class Person:
def __format__(self, format):
if(format == ‘age’):
return ’23’
return ‘None’
print(format(Person(), "age"))
▧ 输出
23
在这里,我们重写 Person
类的 __format__()
方法。
它现在接受一个format
参数,如果它等于'age'
,则返回 23。如果未指定格式,则返回 None
。
format()
函数在内部运行 Person().__format__("age")
以返回 23。
内置 format() Vs 字符串 format()
format()
函数类似于 字符串格式 的方法。在内部,这两种方法都调用对象的 __format__()
方法。
虽然内置 format()
函数是在内部使用 __format__()
格式化对象的低级实现,但字符串 format()
则是更高级别的实现,能够对多个对象字符串执行复杂的格式化操作。
frozenset()
函数返回一个不可变的 frozenset 对象,该对象使用给定的迭代器中的元素进行初始化。Frozen(冻结集)只是 Python 集对象的一个不可变版本。虽然可以随时修改集合的元素,但冻结集合的元素在创建后保持不变。因此,Frozen(冻结集)可以用作字典中的键或另一个集合的元素。但与集合一样,它是无序的(元素可以设置在任何索引处)。
frozenset() 语法
frozenset()
函数的语法是:
frozenset([iterable])
frozenset() 参数
frozenset()
函数接受一个参数:
- iterable (可选参数) – 包含用于初始化冻结集合的元素的迭代器(可迭代对象),迭代器可为集合、字典、元组等。
frozenset() 返回值
frozenset()
函数返回一个不可变的 frozenset
,它用给定的迭代器中的元素初始化。
如果没有传递参数,则返回一个空的 frozenset
。
✎示例1-frozenset() 如何工作
# 元音元组
vowels = ('a', 'e', 'i', 'o', 'u')
fSet = frozenset(vowels)
print('冻结的集合为:', fSet)
print('空的冻结集合是:', frozenset())
# frozensets 是不可变的,添加元素则报错!
fSet.add('v')
▧ 输出
冻结集合为: frozenset({'a', 'o', 'u', 'i', 'e'}) 空的冻结集合是: frozenset() Traceback (most recent call last): File "<string>, line 8, in <module> fSet.add('v') AttributeError: 'frozenset' object has no attribute 'add'
✎示例2: 针对字典的 frozenset()
当你使用字典作为冻结集合的迭代器(可迭代对象)时,它只需要用字典的键来创建集合。
# 随机字典
person = {"name": "TianTian", "age": 23, "sex": "male"}
fSet = frozenset(person)
print('冻结集合为:', fSet)
▧ 输出
冻结集合为: frozenset({'name', 'sex', 'age'})
Frozenset 操作
与普通集合一样,冻结集合也可以执行不同的操作,如copy
, difference
, intersection
, symmetric_difference
, 与 union
.
# Frozensets
# 初始化 A 与 B
A = frozenset([1, 2, 3, 4])
B = frozenset([3, 4, 5, 6])
# 复制 frozenset
C = A.copy() # 输出: frozenset({1, 2, 3, 4})
print(C)
# 并集
print(A.union(B)) # 输出: frozenset({1, 2, 3, 4, 5, 6})
# 交集
print(A.intersection(B)) # 输出: frozenset({3, 4})
# 差异
print(A.difference(B)) # 输出: frozenset({1, 2})
# 对称差异
print(A.symmetric_difference(B)) # 输出: frozenset({1, 2, 5, 6})
▧ 输出
frozenset({1, 2, 3, 4}) frozenset({1, 2, 3, 4, 5, 6}) frozenset({3, 4}) frozenset({1, 2}) frozenset({1, 2, 5, 6})
同样,也可以使用其他设置方法,例如 isdisjoint
、issubset
和 issuperset
。分别为:判断两个集合是否包含相同元素、判断集合所有元素是否都包含在指定集合中、判断指定集合的所有元素是否都包含在原始集合中。
# Frozensets
# 初始化 A, B 与 C
A = frozenset([1, 2, 3, 4])
B = frozenset([3, 4, 5, 6])
C = frozenset([5, 6])
# isdisjoint() 方法
print(A.isdisjoint(C)) # 输出: True
# issubset() 方法
print(C.issubset(B)) # 输出: True
# issuperset() 方法
print(B.issuperset(C)) # 输出: True
▧ 输出
True True True
getattr()
函数返回对象的命名属性的值。如果未找到,则返回提供给函数的默认值。
例如
class Student:
marks = 88
name = 'TianTian'
person = Student()
name = getattr(person, ‘name’)
print(name)
marks = getattr(person, ‘marks’)
print(marks)
# 输出: TianTian
# 88
getattr() 语法
getattr()
函数的语法是:
getattr(object, name[, default])
上面的语法等价于:
object.name
getattr() 参数
getattr()
函数接受多个参数:
- object – 要返回其命名属性值的对象
- name – 包含属性名称的字符串
- default (可选参数) – 未找到命名属性时返回的值
getattr() 返回值
getattr()
函数返回:
- 给定对象的命名属性值
default
, 如果没有找到命名属性AttributeError
异常,如果未找到命名属性且未定义默认值
✎示例 1-getattr() 如何工作?
class Person:
age = 18
name = "TianTian"
person = Person()
print(‘The age is:’, getattr(person, “age”))
print('The age is:', person.age)
▧ 输出
The age is: 18 The age is: 18
✎示例 2:未找到命名属性时的 getattr()
class Person:
age = 23
name = "TianTian"
person = Person()
# 当提供默认值时
print(‘The sex is:’, getattr(person, ‘sex’, ‘Male’))
# 当没有提供默认值时
print(‘The sex is:’, getattr(person, ‘sex’))
▧ 输出
The sex is: Male AttributeError: 'Person' object has no attribute 'sex'
Person
类中不存在命名属性sex。因此,当使用了默认值 Male
,调用 getattr()
函数时,它返回 Male
。
但是,如果我们不提供任何默认值,当找不到命名属性sex时,它会引发一个 AttributeError
说对象没有sex属性。
globals()
函数返回当前全局符号表的字典。
符号表是由编译器维护的数据结构,其中包含有关程序的所有必要信息。
这些包括变量名、方法、类等。
符号表主要有两种:
- 本地符号表
- 全局符号表
本地符号表存储与程序本地范围相关的所有信息,在 Python 中使用 locals()
函数访问。
局部作用域可以在函数内、类内等。
同样,全局符号表存储与程序全局范围相关的所有信息,并在 Python 中使用 globals()
函数访问。
全局作用域包含与任何类或函数无关的所有函数、变量。
推荐阅读以前的教程:Python 中的命名空间和作用域
globals() 语法
globals 表字典是当前模块的字典(在函数内部,这是定义它的模块,而不是调用它的模块)。
globals()
函数的语法为:
globals()
globals() 参数
globals()
函数不带任何参数。
globals() 返回值
globals()
函数返回当前全局符号表的字典。
✎示例1-globals() 如何工作?
globals()
▧ 输出
{'In': ['', 'globals()'], 'Out': {}, '_': '', '__': '', '___': '', '__builtin__': <module 'builtins' (built-in)>, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '_dh': ['/home/repl'], '_i': '', '_i1': 'globals()', '_ih': ['', 'globals()'], '_ii': '', '_iii': '', '_oh': {}, '_sh': <module 'IPython.core.shadowns' from '/usr/local/lib/python3.5/dist-packages/IPython/core/shadowns.py'>, 'exit': <IPython.core.autocall.ExitAutocall at 0x7fbc60ca6c50>, 'get_ipython': <bound method InteractiveShell.get_ipython of <IPython.core.interactiveshell.InteractiveShell object at 0x7fbc6478ee48>>, 'quit': <IPython.core.autocall.ExitAutocall at 0x7fbc60ca6c50>}
输出显示当前程序的所有全局变量和其他符号。
✎示例2-使用 global() 修改全局变量
age = 23
globals()['age'] = 25
print('The age is:', age)
▧ 输出
The age is: 25
在这里,由于全局符号表还存储了所有全局变量,即在这种情况下,age的值可以使用globals()函数进行更改。
使用变量age的键访问返回的字典,并将其修改为 25。
exec()
函数执行动态创建的程序,该程序可以是字符串或代码对象。
exec() 语法
exec()
的语法是:
exec(object, globals, locals)
exec() 参数
exec()
接受三个参数:
- object – 字符串或代码对象
- globals (可选参数) – 字典
- locals (可选参数)- 一个映射对象。字典是 Python 中标准和常用的映射类型
globals和locals的使用将在本文中有做说明。
exec() 返回值
exec()
不返回值,它返回为 None
。
✎示例1-exec() 如何工作?
program = 'a = 5\nb=10\nprint("Sum =", a+b)'
exec(program)
▧ 输出
Sum = 15
在这里,字符串对象program被传递给执行程序的exec()。在这种情况下,globals和locals被省略。
✎示例2-允许用户提供输入
program = input('请输入程序:')
exec(program)
▧ 输出
请输入程序: [print(item) for item in [1, 2, 3]] 1 2 3
如果想从用户那里获取允许多行代码(使用 '\n'
)的 Python 代码,可以在使用 exec()
之前使用 compile()
函数。
了解有关 Python 中 compile() 函数的更多信息,请查看:[Python]函数⁽¹⁹⁾|内置函数⁽¹⁾。
使用 exec() 的注意事项
同样,当使用的是 Unix 系统(macOS、Linux 等)并且导入了 os
模块。os 模块提供了使用操作系统功能,例如读取或写入文件。
如果允许用户使用 exec(input())
输入值,则用户可能会使用命令 os.system('rm -rf *')
发出更改文件甚至删除所有文件的命令。
如果在代码中使用 exec(input())
,最好检查用户可以使用哪些变量和函数。可以使用 dir()
函数查看哪些变量和函数可用。
from math import *
exec('print(dir())')
▧ 输出
['In', 'Out', '_', '__', '___', '__builtin__', '__builtins__', '__name__', '_dh', '_i', '_i1', '_i2', '_ih', '_ii', '_iii', '_oh', '_sh', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exit', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'get_ipython', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'quit', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
限制 exec() 中可用函数和变量的使用
通常情况下, exec()
中使用的所有可用函数和变量可能都不需要,甚至存在安全漏洞。你可以通过将可选的 globals
和 locals
参数(字典)传递给 exec()
函数来限制这些变量和函数的使用。
1. globals 与 locals 参数都被省略
如果两个参数都被省略(如我们前面的例子),预期由 exec()
执行的代码将在当前作用域中执行。你可以使用以下代码检查可用的变量和函数:
exec('print(dir())')
2. 传递 globals 参数; locals 参数省略
globals和locals参数(字典)分别用于全局变量和局部变量。如果省略locals字典,则默认为globals字典。意思是,globals变量将用于全局变量和局部变量。
Note: 你可以分别使用 globals() 和 locals() 内置方法在 Python 中检查当前的全局和局部字典。
3. 将空字典作为 globals 参数传递
from math import *
exec('print(dir())', {})
# 此代码将引发异常
# exec('print(sqrt(9))', {})
如果将空字典作为globals传递,则只有__builtins__可用于对象(exec() 的第一个参数)。即使我们在上面的程序中导入了 math 模块,尝试访问 math 模块提供的任何函数都将会引发异常。
▧ 输出
['__builtins__']
使某些函数可用
from math import *
exec('print(dir())', {'sqrt': sqrt, 'pow': pow})
# 对象可以用 sqrt() 模块
exec('print(sqrt(9))', {'sqrt': sqrt, 'pow': pow})
在这里,由 exec()
执行的代码也可以有 sqrt()
和 pow()
函数以及 __builtins__
。
可以根据你的意愿更改函数的名称
from math import *
exec('print(dir())', {'squareRoot': sqrt, 'pow': pow})
# 对象可以有 squareRoot() 模板
exec('print(squareRoot(9))', {'squareRoot': sqrt, 'pow': pow})
在上面的程序中,squareRoot()
计算平方根(类似 sqrt()
的功能)。如果,再尝试使用 sqrt()
则会引发异常。
限制使用内置函数
可以通过为globals字典中的‘__builtins__’赋予值None来限制__builtins__的使用。
exec(object, {'__builtins__': None})
4. 传递 globals 与 locals 字典
可以通过传递locals字典使所需的函数和变量可用。例如:
from math import *
globalsParameter = {'__builtins__' : None}
localsParameter = {'print': print, 'dir': dir}
exec('print(dir())', globalsParameter, localsParameter)
▧ 输出
['dir', 'print']
在这里,exec()
函数只能执行两个内置方法 print()
和 dir()
。
需要注意的是,exec()
执行代码不返回任何值(返回 None
)。因此,不能在函数定义之外使用 return
和 yield
语句。
如果对象具有给定的命名属性,则
hasattr()
函数返回 true,否则返回 false。
hasattr() 语法
hasattr()
函数的语法:
hasattr(object, name)
hasattr()
调用 getattr()
来检查是否要引发AttributeError。
hasattr() 参数
hasattr()
函数接受两个参数:
- object – 要检查其命名属性的对象
- name – 要搜索的属性的名称
hasattr() 返回值
hasattr()
函数返回:
- True – 如果对象具有给定的命名属性
- False – 如果对象没有给定的命名属性
✎示例-hasattr() 如何工作?
class Person:
age = 18
name = 'TianTian'
person = Person()
print('Person类有 age?:', hasattr(person, 'age'))
print('Person类有 salary?:', hasattr(person, 'salary'))
▧ 输出
Person类有 age?: True Person类有 salary?: False
help()
函数调用内置的 Python 帮助系统。
help() 语法
help()
的语法为:
help(object)
help() 参数
help()
函数最多接受一个参数:
- object (可选参数) – 你想生成给定对象的帮助
help() 如何工作?
help()
函数用于交互式使用。当你需要帮助编写 Python 程序和使用 Python 模块时,建议在解释器中使用它。
Note: 以下,将对象被传递给 help()
(不是字符串)
在 Python shell 上试试运行以下:
>>> help(list)
>>> help(dict)
>>> help(print)
>>> help([1, 2, 3])
Note: 以下,我们将字符串作为参数传递给 help()
如果 string
作为参数传递,则给定的 string 将作为模块、函数、类、方法、关键字或文档主题的名称进行查找,并打印帮助页面。
不妨在 Python shell 上试试这些。
>>> help('random thing')
>>> help('print')
>>> help('def')
>>> from math import *
help('math.pow')
Note: 以下,无参数传递给 help()
如果未传递任何参数,Python 的帮助实用程序(交互式帮助系统)将在控制台上启动。
>>> help()
然后,你可以输入主题名称以获取有关编写 Python 程序和使用 Python 模块的帮助。例如:
help> True
help> 'print'
help > print
要退出帮助实用程序并返回到解释器,则需要键入 quit
并按回车键。
help > quit
hex()
函数将整数转换为相应的十六进制字符串。
hex() 语法
hex()
的语法是:
hex(x)
hex() 参数
hex()
函数接受单个参数:
x – 整数(int
对象或它必须定义返回整数的 __index__()
方法)
hex() 返回值
hex()
函数将一个整数以字符串形式转换为相应的十六进制数并返回。
返回的十六进制字符串以前缀 0x
开头,表示它是十六进制形式。
✎示例1-hex() 如何工作?
number = 435
print(number, 'in hex =', hex(number))
number = 0
print(number, 'in hex =', hex(number))
number = -34
print(number, 'in hex =', hex(number))
returnType = type(hex(number))
print('返回 hex() 的类型是', returnType)
▧ 输出
435 in hex = 0x1b3 0 in hex = 0x0 -34 in hex = -0x22 返回 hex() 的类型是 <class 'str'>
如果需要查找浮点数的十六进制表示,则需要使用 float.hex()
方法。
✎示例2-浮点数的十六进制表示
number = 2.5
print(number, 'in hex =', float.hex(number))
number = 0.0
print(number, 'in hex =', float.hex(number))
number = 10.5
print(number, 'in hex =', float.hex(number))
▧ 输出
2.5 in hex = 0x1.4000000000000p+1 0.0 in hex = 0x0.0p+0 10.5 in hex = 0x1.5000000000000p+3
hash()
函数返回一个对象的哈希值(如果对象有哈希值)。哈希值只是用于在快速查找字典期间比较字典键的整数。
例如
text = 'Python Programming'
# 计算文本的哈希值
hash_value = hash(text)
print(hash_value)
# 输出: 3604634668836859759
hash() 语法
hash()
函数的语法:
hash(object)
hash() 参数
hash()
函数接受一个参数:
- object – 要返回其哈希值的对象 (整型, 字符串, 浮点)
hash() 返回值
hash()
函数返回对象的哈希值。
✎示例1-hash() 如何工作?
# 整数哈希值:不变
print(‘Hash for 181 is:’, hash(181))
# 十进制哈希值
print(‘Hash for 181.23 is:’,hash(181.23))
# 字符串的哈希值
print(‘Hash for Python is:’, hash(‘Python’))
▧ 输出
Hash for 181 is: 181 Hash for 181.23 is: 530343892119126197 Hash for Python is: -1471430142086338170
✎示例 2-hash() 用于不可变元组对象
hash()
函数仅适用于作为元组的不可变对象。
# 存储元音的元组
vowels = ('a', 'e', 'i', 'o', 'u')
print(‘hash 值为:’, hash(vowels))
▧ 输出
hash 值为: -695778075465126279
hash() 如何在自定义的对象工作?
如上所述,hash()
方法在内部调用 __hash__()
方法。因此,任何对象都可以为自定义哈希值覆盖 __hash__()
。
但是为了正确的哈希实现, __hash__()
应该总是返回一个整数。而且,必须实现 __eq__()
和 __hash__()
方法。
以下则是正确 __hash__()
方法覆盖的情况:
__eq__() | __hash__() | 描述 |
---|---|---|
已定义 (默认) | 已定义 (默认) | 如果保持原样,所有对象则比较不相等(除了它们自己) |
(如果可变) 已定义 | 不应被定义 | hashable 集合的实现要求 key 的 hash 值是不可变的 |
未定义 | 不应被定义 | 如果未定义__eq__() ,则不应定义 __hash__() 。 |
定义 | 未定义 | 类实例将不能用作hashable 集合。__hash__() 隐式设置为 None 。如果尝试检索 hash,则引发 TypeError 异常。 |
定义 | 从父类那里保留 | __hash__ = <ParentClass>.__hash__ |
定义 | 不想 hash | __hash__ = None 。如果尝试检索 hash,则引发 TypeError 异常。 |
✎示例 3-通过覆盖 __hash__() 对自定义对象进行 hash()
class Person:
def __init__(self, age, name):
self.age = age
self.name = name
def __eq__(self, other):
return self.age == other.age and self.name == other.name
def __hash__(self):
print(‘hash 值是:’)
return hash((self.age, self.name))
person = Person(23, 'TianTian')
print(hash(person))
▧ 输出
hash 值是: 3785419240612877014
Note: 你不必实现 __eq__()
方法,因为它是默认为所有对象创建的。
input()
函数是从用户那里获取输入并返回它。
例如
name = input(“Enter your name: “)
print(name)
# 输出: Enter your name: "TianTian"
# TianTian
input() 语法
input()
函数的语法是:
input([prompt])
input() 参数
input()
函数接受一个可选的参数:
- prompt (可选参数) – 写入标准输出(通常是屏幕)的字符串,没有尾随换行符
input() 返回值
input()
函数从输入中读取一行(通常来自用户),通过删除尾随的换行符将该行转换为字符串,并返回它。如果读取 EOF,则会引发 EOFError
异常。
✎示例1-input() 如何工作?
# 获取用户输入
inputString = input()
print('输入的字符串为:', inputString)
▧ 输出
Python is interesting. 输入的字符串为: Python is interesting
✎示例2-通过提示获取用户输入
# 获取用户输入
inputString = input(‘请输入字符串:’)
print('你输入的字符串是:', inputString)
▧ 输出
请输入字符串: Python is interesting. 你输入的字符串是: Python is interesting
id()
函数返回对象的身份号(唯一整数)。
id() 语法
id()
的语法是:
id(object)
id() 参数
id()
函数接受单个参数的对象 object。
id() 返回值
id()
函数返回对象的身份号。这是一个整数,对于给定的对象是唯一的,并且在其生命周期内保持不变。
✎示例1-id() 如何工作?
class Foo:
b = 5
dummyFoo = Foo()
print('id of dummyFoo =',id(dummyFoo))
▧ 输出
id of dummyFoo = 2078576426960
✎更多关于 id() 的例子
print('id of 5 =',id(5))
a = 5
print('id of a =',id(a))
b = a
print('id of b =',id(b))
c = 5.0
print('id of c =',id(c))
▧ 输出
id of 5 = 140472391630016 id of a = 140472391630016 id of b = 140472391630016 id of c = 140472372786520
重要的是要注意 Python 中的一切都是对象,包括偶数和类等。
因此,整数 5
具有唯一的 id。整数 5
的 id 在生命周期内保持不变。浮点数 5.5
和其他对象的情况类似。
isinstance()
函数为检查对象(第一个参数)是否是 classinfo 类(第二个参数)的实例或子类。
例如
numbers = [1, 2, 3, 4, 2, 5]
# 检查数字是否是列表的实例
result = isinstance(numbers, list)
print(result)
# 输出: True
isinstance() 语法
isinstance()
的语法是:
isinstance(object, classinfo)
isinstance() 参数
isinstance()
接受两个参数:
- object – 被检查的对象
- classinfo – 类、类型或类和类型的元组
isinstance() 返回值
isinstance()
返回:
- 如果object是类的实例或子类或元组的任何元素,则为True
- 否则为
False
如果classinfo不是类或类型元组,则会引发TypeError异常。
✎示例1-isinstance() 如何工作?
class Foo:
a = 5
fooInstance = Foo()
print(isinstance(fooInstance, Foo))
print(isinstance(fooInstance, (list, tuple)))
print(isinstance(fooInstance, (list, tuple, Foo)))
▧ 输出
True False True
✎示例2-用原始类型使用 isinstance()
numbers = [1, 2, 3]
result = isinstance(numbers, list)
print(numbers,'instance of list?', result)
result = isinstance(numbers, dict)
print(numbers,'instance of dict?', result)
result = isinstance(numbers, (dict, list))
print(numbers,'instance of dict or list?', result)
number = 5
result = isinstance(number, list)
print(number,'instance of list?', result)
result = isinstance(number, int)
print(number,'instance of int?', result)
▧ 输出
[1, 2, 3] instance of list? True [1, 2, 3] instance of dict? False [1, 2, 3] instance of dict or list? True 5 instance of list? False 5 instance of int? True
下篇继续介绍 Python 中内置函数……
转载请注明:XAMPP中文组官网 » [Python]函数⁽²⁰⁾|内置函数⁽²⁾