三元运算
# 书写格式
result = 值1 if 条件 else 值2
# 如果条件成立,那么将 “值1” 赋值给result变量,否则,将“值2”赋值给result变量
比如:
result = "good" if 1 > 0 else "well"
print(result)
输出结果:
good
深浅拷贝
对于 数字 和 字符串 而言,赋值、浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址。对于字典、元祖、列表 而言,进行赋值、浅拷贝和深拷贝时,其内存地址的变化是不同的。
浅拷贝,在内存中只额外创建第一层数据。
深拷贝,在内存中将所有的数据重新创建一份(排除最后一层,即:python内部对字符串和数字的优化)
函数
定义函数
def 函数名(形参,形参,形参):
函数体
return ‘###’执行函数
//这种方式传的实参默认一一对应形参
函数名(实参)
//这种方式传参,可以不用管形参的顺序,因为传的参数已经指定了形参
函数名(形参=实参,形参=实参,形参=实参)
注意:方法默认有返回值,默认返回None,可以用return 返回任何想要返回的值,可以没有return,最后一行执行的结果作为返回值
函数的参数
位置参数(普通参数)
def power(x):
return x**2
上述函数,参数x就是一个位置参数,如果有位置参数,必传。
默认参数
def power(x, n=3):
return x ** n
上述函数,参数n就是一个默认参数,我们可以只传一个参数,也可以传两个,如果只传一个,n参数默认为3。
注意:必选参数在前,默认参数在后,否则Python的解释器会报错。当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。默认参数必须指向不变对象。
可变参数
参数前面加了一个号就表示接收一个可变参数,实际上会把传入的参数变成一个tuple,Python允许你在list或tuple前面加一个号,把list或tuple的元素变成可变参数传进去。
def calc(*arg):
for item in arg:
print(item)
data = [5, 6, 7]
//如果直接这样传,列表会变成tuple的一个元素([5, 6, 7],)
calc(data)
calc(*data)
关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict 。
def calc(**arg):
for item in arg:
print(item)
extra = {'city': 'Beijing', 'job': 'Engineer'}
// Python允许你在dict前面加两个*号,把dict的元素变成可变参数传进去
calc(**extra)
命名关键字参数
如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:
def person(name, age, *, city, job):
print(name, age, city, job)
person('Jack', 24, city='Beijing', job='Engineer')
和关键字参数*kw不同,命名关键字参数需要一个特殊分隔符,*后面的参数被视为命名关键字参数。
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:
def person(name, age, *args, city, job):
print(name, age, args, city, job)
命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错,因为系统会错认为是位置参数,但是实际上位置参数只有两个。命名关键字参数可以有缺省值,从而简化调用:
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
由于命名关键字参数city具有默认值,调用时,可不传入city参数:
person('Jack', 24, job='Engineer')
使用命名关键字参数时,要特别注意,如果没有可变参数,就必须加一个作为特殊分隔符。如果缺少,Python解释器将无法识别位置参数和命名关键字参数:
def person(name, age, city, job):
//缺少 *,city和job被视为位置参数
pass
全局和局部变量
全局变量,在任何位置都可以使用(约定,全局变量名字全部大写)
局部变量,在局部内使用,局部外使用不了。
PERSON = "good"
def fun1():
# 局部变量,只能内部使用
a = 123
# 局部变量和全局变量一样,不影响全局变量,只是局部内部有一个名字和全局一样的变量而已
# 如果这样声明,则修改的是全局的变量
# global PERSON
PERSON = "fanda"
print(a)
print(PERSON)
fun1()
print(PERSON)
lambda表达式
def test(args1, args2):
print(args1 + args2)
test2 = lambda args1, args2: print(args1 + args2)
上述两个方法的的实现是等价的。
内置函数
abs 取绝对值
print(abs(-123))
all 传入可迭代对象,循环参数,如果每个元素都为真,返回True,否则,返回False
假的数据,0,None,"",(),{},即0,None,空值,返回False
print(bool(0))
print(bool(""))
print(bool(()))
print(bool({}))
返回False
print(all([11, "34", ""]))
any 传入可迭代对象,循环参数,如果有一个元素为真,返回True
返回True
print(any([11, "34", ""]))
ascii,传入对象,找到对象中的__repr__方法,返回其执行结果
print(ascii("fsfsdfsf"))
a = bin(11) # 二进制
b = oct(11) # 八进制
c = int(11) # 十进制
d = hex(11) # 十六进制
print(a, b, c, d)
结果 ,0b1011 0o13 11 0xb
结果是一个元祖,元素分别是商和余数
result = divmod(10,3)
print(result)
把字符串变成表达式,只处理简单的表达式,有返回值
print(eval("1+3"))
print(eval("a+100+b", {"a": 100, "b": 50}))
这个方法才可执行复杂的表达式,没返回值,相当于直接执行python代码
exec("for i in range(10) : print(i)")
li = [22, 3, 53]
判断某个对象是否是某个类型的
print(isinstance(li, list))
map() 方法,map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
result = filter(lambda x: x > 10, [1, 4, 9, 11, 34, 43, 64])
print(type(result))
print(list(result))
for item in result:
print(item)
由于结果result是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。
再看reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
如果要把序列[1, 3, 5, 7, 9]变换成整数13579,用reduce实现如下:
print(reduce(lambda x, y: x * 10 + y, [1, 3, 5, 7, 9]))
和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
result = filter(lambda x: x > 10, [1, 4, 9, 11, 34, 43, 64])
print(type(result))
print(list(result))
for item in result:
print(item)
可见用filter()这个高阶函数,关键在于正确实现一个“筛选”函数。
注意到filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。
sorted()函数可以对list进行排序:
li = [1, 4, 5, -3, -64, 0, -43]
这个方法返回一个新的值 ,之前的值不变
print(sorted(li))
//结果[-64, -43, -3, 0, 1, 4, 5]
此外,sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:
print(sorted(li, key=abs))
//结果[0, 1, -3, 4, 5, -43, -64]
key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序,然后按照对应关系返回list相应的元素。默认是从小到大排序的,如果想要从大到小排序,可以再增加一个参数,如下:
print(sorted(li, key=abs, reverse=True))
//结果[-64, -43, 5, 4, -3, 1, 0]
sorted()是一个高阶函数。用sorted()排序的关键在于实现一个映射函数。
递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
举个例子,我们来计算阶乘n! = 1 x 2 x 3 x … x n,用函数fact(n)表示,可以看出:
fact(n) = n! = 1 x 2 x 3 x … x (n-1) x n = (n-1)! x n = fact(n-1) x n
所以,fact(n)可以表示为n x fact(n-1),只有n=1时需要特殊处理。
于是,fact(n)用递归的方式写出来就是:
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
如果我们计算fact(5),可以根据函数定义看到计算过程如下:
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
利用函数编写如下数列:
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368…
def func(arg1, arg2):
if arg1 == 0:
print(arg1, arg2)
arg3 = arg1 + arg2
print(arg3)
if arg3 > 10000:
return
func(arg2, arg3)
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。上述代码如果不加判断来终结函数,将会报错