python入门第十六节

函数

  • 自定义函数
    • 格式
    • return用法
    • 文档注释
    • 常用函数
      • help([object])
      • abs(x)
      • divmod(a,b)
      • max(iterable[, key, default]) / max(arg1, arg2, *args[, key])
      • min(iterable[, key, default]) / min(arg1, arg2, *args[,key])
      • pow(base, exp[, mod])
      • round(number [, ndigits])
      • sum(iterable, start=0)
    • 参数传递
      • 参数分类
        • 必须参数
        • 关键字参数
        • 默认参数
        • 不定长参数
        • 特殊参数
        • 匿名函数
  • 封包、解包
    • 封包
    • 解包
  • 命名空间与作用域
    • 命名空间
      • 内置命名空间
        • dir([object])
      • 全局命名空间
      • 局部命名空间
      • 命名空间顺序
    • 作用域
      • 局部作用域
        • 闭包函数外的函数中
      • 全局作用域
      • 内建作用域
      • global 和 nonlocal

自定义函数

格式

def func_name(arg1[,arg2,...,argN])
	fun_body
  • 形参: 函数定义时声明的参数。
  • 实参: 函数调用时传入的参数。
  • 函数只需要定义一次,就可以被多次使用。
  • 当函数被调用时,才执行函数体,定义时不执行。
def plus(num):
	print(num + 1)
""" 调用函数 """
plus(2) # 3
plus(5) # 6
"""
输出函数的引用,显示地址
f和plus指向同一个函数
"""
f = plus
print(plus)
print(f)
f(2) # 3
f(5) # 6

return用法

  • 把后面跟着的对象返回给函数调用方,并结束所在的函数
  • return 后面可以跟单个对象,多个对象,表达式,不跟
  • return 后面什么都不跟,等价于 return None
  • 函数执行时,没有遇到return,等价于return None
# 返回单个对象
def add1(left, right):
	res = left + right
	return res
# 返回一个表达式
def add2(left, right):
	return left + right
# 返回多个对象, 自动打包成一个元组
def add3(left, right):
	res1 = left + right
	res2 = left * right
	return res1, res2
# 返回多个表达式
def add4(left, right):
	return left + right, left * right
# return None
def add5(left, right):
	print(left + right)
	return
# return None
def add6(left, right):
	pass
print(add1(3, 4))
print(add2(3, 4))
print(add3(3, 4))
print(add4(3, 4))
print(add5(3, 4))
print(add6(3, 4))

文档注释

def div_mod(x, y):
"""
Return the tuple (x//y, x%y).
:param x: number(except complex)
:param y: number(except complex)
:return: (x//y, x%y)
"""
# 上面的这段多行注释即文档注释
div = x // y
mod = x % y
return div, mod
# __doc__属性存放了文档注释
print(div_mod.__doc__)
print(divmod.__doc__)

常用函数

help([object])

  • 启动内置的帮助系统
  • 如果没有实参,解释器控制台里会启动交互式帮助系统
  • 如果实参是一个字符串,则在模块、函数、类、方法、关键字或文档主题中搜索该字符串,并在控制台上打印帮助信息
  • 如果实参是其他任意对象,则会生成该对象的帮助页
help() # 启动交互式帮助系统
help("keywords") # 查看关键字
help(list) # 生成list的帮助页

abs(x)

  • x:可以是整数,浮点数,布尔型,复数。
  • 返回一个数的绝对值,如果参数是一个复数,则返回它的模。
print(abs(-6)) # 6,参数是整数
print(abs(6.9)) # 6.9,参数是浮点数
print(abs(3+4j)) # 5.0,参数是复数

divmod(a,b)

  • 返回一个元组(a \ b,a % b)
print(divmod(7, 3)) # (2, 1)
print(7 // 3, 7 % 3)
print(divmod(-9, 2)) # (-5, 1)
print(-9 // 2, -9 % 2)

max(iterable[, key, default]) / max(arg1, arg2, *args[, key])

  • 返回给定数据的最大值
print(max([3, 1, 2]))
print(max(3, 1, 2))
print(max('1', '2', '3', '10'))
print(max([], default=666))
print(max([1, 2, -3], key=abs))

min(iterable[, key, default]) / min(arg1, arg2, *args[,key])

  • 返回给定数据的最小值
print(min([3, 1, 2]))
print(min(3, 1, 2))
print(min('20', '2', '3', '10'))
print(min([], default=666))
print(min([-9, 2, -3], key=abs))

pow(base, exp[, mod])

  • 返回 base 的 exp 次幂
  • 如果 mod 存在,则返回 base 的 exp 次幂对 mod 取余
print(pow(-2, 3)) # -2**3 = -8
print(pow(-2, 3, 3)) # -2**3 % 3 = 1

round(number [, ndigits])

  • number:数字
  • ndigits:保留的小数点位数
  • 返回 number 四舍五入到小数点后 ndigits 位精度的值,如果 ndigits 被省略或为None,则返回值为整数,否则返回值和 number 类型相同
pi = 3.141592653
print(round(pi))
print(round(pi, ndigits=None))
print(round(pi, ndigits=1))
print(round(pi, ndigits=2))
print(round(pi, ndigits=3))
print(round(3.141592653, ndigits=0))
print(round(-3.141592653, ndigits=0))
print(round(0.141592653, ndigits=0))
print(round(-0.141592653, ndigits=0))
# 作为了解
print(round(0.5))
print(round(1.5))
print(round(2.5))
print(round(3.5))
print(round(2.665, ndigits=2))
print(round(2.675, ndigits=2))

sum(iterable, start=0)

  • 从 start 开始自左向右对 iterable 的元素求和,并返回
print(sum([1, 2, 3]))
print(sum([1, 2, 3], start=100))
print(sum({1: 2, 3: 4, 5: 6}, start=100))

参数传递

  • 传不可变对象 & 传可变对象
def func(b):
	print(id(a),a)
	print(id(b),b)


a = 789
func(a)


def func(b):
	print(id(a), a)
	print(id(b), b)


a = [789]
func(a)


def func(b):
	b.append(345)
	
	
a = [789]
func(a)
print(a)

参数分类

必须参数
  • 必须接收一个实参,否则报错
  • 实参通常可以传位置参数,也可以传关键字参数
def func(a, b):
	print(a - b)'


func(4, 3) # 1
func(3, 4) # -1
func(a=3, b=4) # -1
关键字参数
  • 实参按照关键字传给对应的形参,与位置无关
  • 关键字参数必须放在位置参数的后面
def func(a, b):
	print(a - b)


func(a=3, b=4)
func(3, b=4)
默认参数
  • 没有传实参时,使用默认值,有传实参,使用实参
def func(a, b=4):
	print(a - b)


func(3)
func(3, 5)
不定长参数
  • *args:接收[0, +∞]个位置参数,贪婪的,将它们打包成一个元组,如果没有接收
    到实参,则为空元组。
  • **kwargs:接收[0, +∞]个关键字参数,贪婪的,将它们打包成一个字典,如果没有
    接收到实参,则为空字典。必须放在所有形参的最后。
def func(*args):
	print(args)


func()
func(3, 1, 4, 6)


def func(**kwargs):
	print(kwargs)


func()


func(a=3, b=2, c=4)
def func(*args, **kwargs):
	print(args)
	print(kwargs)


func()
func(1, 2, a=3, b=4)
特殊参数
  • 默认情况下,实参的传递形式可以是位置参数或关键字参数
  • 可以用 / 和 * 来限制参数的传递形式
  • 其中 / 为仅限位置参数,限制在它之前的形参只能接收位置参数
  • 其中 * 为仅限关键字参数,限制在它之后的形参只能接收关键字参数
  • 这两个特殊参数只是为了限制参数的传递形式,不需要为它们传入实参
def func(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
	pass


func(1, 2, 3, kwd1=4, kwd2=5)
func(1, 2, pos_or_kwd=3, kwd1=4, kwd2=5)
匿名函数
  • 格式: lambda [arg1 [, arg2, … argN]] : expression
  • 匿名函数的参数可以有多个, 但是后面的 expression 只能有一个
  • 匿名函数返回值就是 expression 的结果,而不需要 return 语句
  • 匿名函数可以在需要函数对象的任何地方使用(如:赋值给变量、作为参数传入其他函数等),因为匿名函数可以作为一个表达式,而不是一个结构化的代码块
print((lambda: 'It just returns a string')())
f = lambda: 'It just returns a string'
print(f())


(lambda x, y, z: print(x + y + z))(1, 2, 3)
f = lambda x, y, z: print(x + y + z)
f(1, 2, 3)


def call_f(function, a, b, c):
	return function(a, b, c)


print(call_f(lambda x, y, z: x + y + z, 1, 2, 3)

封包、解包

封包

  • 将多个值同时赋值给一个变量时,Python 会自动将这些值封装成一个元组,这个特性称之为封包
tup = 345, 'hello', 789
print(tup)

解包

解包是针对可迭代对象的操作

  • 赋值过程中的解包
a, b, c = [4, 3, 'a']
print(a) # 4
print(b) # 3
print(c) # 'a'

a, *b, c = 'hello'
print(a) # 'h'
print(b) # ['e', 'l', 'l']
print(c) # 'o'

a, *b, c = 'he'
print(a) # 'h'
print(b) # []
print(c) # 'e'

*a, = 'hel'
print(a) # ['h', 'e', 'l']

_, *b, _ = [4, 3, 5, 7]
print(b) # [3, 5]
  • 在可迭代对象前面加一个星号(*),在字典对象前面加双星(**),这中解包方式主要运用在函数传参的过程中
def func(a, b, c):
	print(a, b, c)
"""
在函数传参时, *iterable可以将
该iterable解包成位置参数
"""
tup = (1, 2, 3)
func(*tup)
"""
在函数传参时, **dict可以将
该dict解包成关键字参数
"""
d = {'a': 1, 'b': 2, 'c': 3}
func(*d)
func(**d)

命名空间与作用域

请先看以下程序:

list = [1, 2, 3, 4, 2, 2]
set1 = set(list)
print(list(set1))  # 报错TypeError: 'list' object is not callable

命名空间

  • 定义:命名空间(Namespace)是一个从名称到对象的映射
  • 实现:大部分命名空间当前由 Python 字典实现(内置命名空间由 builtins 模块实现)
  • 作用:提供了在项目中避免名字冲突的一种方法(各个命名空间是独立的,没有任何关系,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响的)

内置命名空间

  • 包含所有 Python 内置对象的名称
  • 在解释器启动时创建,持续到解释器终止
import builtins


print(dir(builtins))  # 输出builtins模块中的所有属性名、方法名、类名构成的列表
dir([object])
  • 不传参数时,返回当前范围内的变量名,函数名,类名构成的列表
  • 传参数时,返回参数的属性名、方法名构成的列表
print(dir())
print(dir(list))

全局命名空间

  • 包含模块中定义的名称,如:变量名、函数名、类名、其它导入的模块名
  • 在模块被读入时创建,持续到解释器终止

局部命名空间

  • 包含函数中定义的名称,如:函数的变量名、参数名
  • 一个函数的局部命名空间在这个函数被调用时创建,持续到函数结束
import random
import copy


def func1(arg1, arg2):
	num = 666
	print(locals())  # 函数会以字典类型返回当前位置的全部局部变量


def func2(arg1, arg2):
	num = 777
	print(locals())

num = 111
func1(222, 333)
func2(444, 555)

print(globals())  # 函数会以字典类型返回当前位置的全部全局变量。
# 在全局作用域, locals()等价于globals()
print(locals())

命名空间顺序

  • 局部命名空间 >> 全局命名空间 >> 内置命名空间

  • eval(expression[, globals[, locals]])

  • exec(object[, globals[, locals]])

    • eval() 和 exec() 函数的功能相似,都可以执行一个字符串形式的 Python 代码
    • 区别:eval()函数只能执行单个表达式,并返回执行的结果;而exec()函数还可以执行代码块,无返回值(return None)
    • 如果globals与locals参数都被忽略,那么它们将遵循命名空间的查找顺序;如果没有被忽略,那么表达式或者代码块在执行时就只能取指定的globals和locals;locals参数如果被忽略,那么它将会取与 globals 相同的值
print(eval('abs(-3)'))
exec('print(abs(-3))')

string = """
import random


num = random.randint(1, 10)
print(num)
"""
exec(string)

a = 1
b = 2


def add():
	a = 3
	print(eval("a + b"))
	print(eval("a + b", {'a': 4, 'b': 5}))
	print(eval("a + b", {'a': 6, 'b': 7}, {'a': 8, 'b': 9}))
	print(eval("a + b", {'a': 6, 'b': 7}, {'a': 8, 'c': 9}))


add()

作用域

  • 定义:Python 程序可以直接访问命名空间的正文区域
  • 作用:决定了哪一部分区域可以访问哪个特定的名称
  • 分类:(L - E - G - B 作用域依次增大)
    • 局部作用域(Local) - L
    • 闭包函数外的函数中(Enclosing) - E
    • 全局作用域(Global) - G
    • 內建作用域(Built-in) - B
  • 规则:在当前作用域如果找不到对应名称,则去更大一级作用域去找,直到最后找不到就会报错
  • 注意:模块、类以及函数会引入新的作用域,而条件语句,循环语句并不会

局部作用域

def func():
	a = 2 # 局部变量
	b = 3 # 局部变量
	print(a + b) # 局部作用域可以调用局部变量a,b
	print(d) # 局部作用域可以调用全局变量d


d = 4 # 全局变量
func()
# print(a, b) # 全局变量不能调用局部变量
闭包函数外的函数中
def outer():
	b = 2 # Enclosing变量b,c
	c = a + 3 # Enclosing可以调用全局变量a
	def inner():
		c = 5 # 局部变量c
		print(a) # 局部作用域可以调用全局变量a
		print(b) # 局部作用域可以调用Enclosing变量b
		print(c) # 优先调用自己作用域内的变量c,而不调用Enclosing变量c
	inner()
a = 1 # 全局变量
outer()

全局作用域

def outer():
	a = c + 2 # Enclosing可以调用全局变量c
	
	def inner():
		b = c + 3 # 局部作用域可以调用全局变量c
		print(a + b) # 局部作用域可以调用Enclosing变量a
	inner()


c = 1 # 全局变量
outer()
print(c) # 调用全局变量c

内建作用域

# abs是内置函数、int是内置类,它们都在内建作用域builtins模块中
num1 = abs(-100)
num2 = int(3.141592653)

global 和 nonlocal

  • 当内部作用域想要给外部作用域的变量重新赋值时,可以用 global 或 nonlocal 关键字
def outer():
	global a, b # 声明当前作用域的a,b为全局变量
	a, b, c, d = 3, 4, 5, 6
	print(a, b)
	
	def inner():
		global a, b # 声明当前作用域的a,b为全局变量
		nonlocal c, d # 声明当前作用域的c,d为Enclosing变量
		a, b, c, d = 7, 8, 9, 0
	inner()
	print(c, d)


a, b = 1, 2
outer()
print(a, b)
def func():
	# 局部有定义a, 则不能使用全局的a
	b = a + 1
	print(b)
	a = 6


a = 9
func()

你可能感兴趣的:(python,开发语言,windows)