最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

[Python]函数⁽²⁰⁾|内置函数⁽²⁾

XAMPP案例 admin 777浏览 0评论

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

 

18-enumerate()

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

19-staticmethod()

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 类一起工作。

 

20-filter()

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)。

 

21-eval()

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()使用这些函数和变量。可通过将可选的globalslocals参数(字典)传递给eval()函数来实现。

1. 当 globals 和 locals 参数都省略时

如果两个参数都被省略(如我们之前的示例),则expression将在当前作用域中执行。你可以使用以下代码检查可用的变量和函数:

print(eval('dir()')

2. 传递 globals 参数;省略 locals 参数

globalslocals参数(字典)分别用于全局变量和局部变量。如果省略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__可用于expressioneval()的第一个参数)。

即使我们在上面的程序中导入了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。所有其他函数和变量都将不可用。


通过传递 globalslocals 字典来限制 eval() 的使用,将使得我们的代码比较安全,特别是当使用用户提供给 eval() 方法的输入时,上面所述的警告。

Note: 有时,即使名称有所限制,eval() 也会不安全。当一个对象及其方法(函数)可以访问时,几乎任何事情都可以做,那么,唯一安全的方法则是验证用户的输入。

 

22-float()

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

 

23-format()

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() 则是更高级别的实现,能够对多个对象字符串执行复杂的格式化操作。

 

24-frozenset()

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 操作

与普通集合一样,冻结集合也可以执行不同的操作,如copydifferenceintersectionsymmetric_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})

同样,也可以使用其他设置方法,例如 isdisjointissubsetissuperset。分别为:判断两个集合是否包含相同元素、判断集合所有元素是否都包含在指定集合中、判断指定集合的所有元素是否都包含在原始集合中。

# 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

 

25-getattr()

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属性。

 

26-globals()

globals() 函数返回当前全局符号表的字典。

 

符号表是由编译器维护的数据结构,其中包含有关程序的所有必要信息。

这些包括变量名、方法、类等。

符号表主要有两种:

  1. 本地符号表
  2. 全局符号表

本地符号表存储与程序本地范围相关的所有信息,在 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。

 

27-exec()

exec() 函数执行动态创建的程序,该程序可以是字符串或代码对象。

 exec() 语法

exec() 的语法是:

exec(object, globals, locals)

 exec() 参数

exec() 接受三个参数:

  • object – 字符串或代码对象
  • globals (可选参数) – 字典
  • locals (可选参数)- 一个映射对象。字典是 Python 中标准和常用的映射类型

globalslocals的使用将在本文中有做说明。

 exec() 返回值

exec() 不返回值,它返回为 None

 

示例1-exec() 如何工作?

program = 'a = 5\nb=10\nprint("Sum =", a+b)'
exec(program)

▧ 输出

Sum = 15

在这里,字符串对象program被传递给执行程序的exec()。在这种情况下,globalslocals被省略。


✎示例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() 中使用的所有可用函数和变量可能都不需要,甚至存在安全漏洞。你可以通过将可选的 globalslocals 参数(字典)传递给 exec() 函数来限制这些变量和函数的使用。

1. globals 与 locals 参数都被省略

如果两个参数都被省略(如我们前面的例子),预期由 exec() 执行的代码将在当前作用域中执行。你可以使用以下代码检查可用的变量和函数:

exec('print(dir())')

2. 传递 globals 参数; locals 参数省略

globalslocals参数(字典)分别用于全局变量和局部变量。如果省略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)。因此,不能在函数定义之外使用 returnyield 语句。

 

28-hasattr()

如果对象具有给定的命名属性,则 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

 

29-help()

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

 

30-hex()

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

 

31-hash()

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__() 方法,因为它是默认为所有对象创建的。

 

32-input()

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

 

33-id()

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 和其他对象的情况类似。

 

34-isinstance()

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]函数⁽²⁰⁾|内置函数⁽²⁾

您必须 登录 才能发表评论!