标签:-- 注释 不同 spec 另一个 关键字 嵌套 简单 作用
# 在for,while,if语句中声明的变量,在这些语句外部依然可以访问
# 这一点与C系的不同,调用locals()就可以发现。
def func():
# for语句
for i in range(10):
sum=i
# if语句
if 10>2:
res=99
# while语句
while True:
a=100
break
# 输出变量
print(sum)
print(res)
print(a)
print(locals())
# {'i': 9, 'sum': 9, 'res': 99, 'a': 100}
#
func()
name="ABC"
def f1():
name="Jack"
def f2():
nonlocal name
# 这里的name指向f1中的name
name="Tom"
print(name)
f2()
print(name)
f1()
#输出为Tom Tom
def foo():
print("foo")
bar()
def bar():
print("bar")
foo()
# 为什么bar定义在foo后面,还是可以正常调用?
# 解释:
# def foo……表明在内存中定义一个变量foo,指向一块内存,内容是函数体
# def bar……表明在内存中定义一个变量bar,指向一块内存,内容是函数体:
# 调用foo()的时候,foo和bar两个变量都定义完毕,因此foo中能够找到bar
# 所以函数可以正常调用
def foo():
print("foo")
bar()
foo()
# 在这里调用为什么报错?
# 解释:
# python解释器运行到foo()时,变量foo已经定义完毕,但bar还没有定义,
# 解释器找不到名为bar的变量,当然找不到里面的函数代码,因此报错
def bar():
print("bar")
def digui(n):
if n==1:
return 1
return n*digui(n-1)
print(digui(10))
递归的效率不高,可以用循环代替,但优势在于算法容易理解
理解递归调用:可以将代码中递归调用的函数名看做函数体的代码,因为函数就是代码块。
import time
today=time.strftime("%Y{}%m{}%d{},%H{}%M{}%S{}",time.localtime()).format("年","月","日","时","分","秒")
# 2019年06月14日,13时39分48秒
data=[]
for i in range(10):
data.append([0 for _ in range(10)])
data[1][5]=1
data[2][3]=5
data[3][9]=20
data[6][2]=99
data[9][0]=30
#本例中演示的是将二维数组变为一维数组
#注意两个for的顺序,与i相关的要放在最后
print([i for item in data for i in item])
我们可以为函数的参数和返回值添加注解,这种注解不具有强制性,是一种类似注释的说明性文字。
def mystrings(n:int,s:str)->str:
return s*n
print(mystrings(10,"a"))
# python并不进行类型检查,下行代码正常运行
print(mystrings(10,10))
# 有三种方法可以获取字符串对应的变量(对象)
class MyClass(object):
a = 100
def show(self):
la = 999
s = "la"
print(locals()[s])
ga = 1024
# 通过getattr函数获取对象成员
s = "a"
print(getattr(MyClass, s))
# 通过globals函数获取全局变量
s = "ga"
print(globals()[s])
# 通过locals函数获取局部变量
mc = MyClass()
mc.show()
import inspect
import re
def varname(p):
for line in inspect.getframeinfo(inspect.currentframe().f_back)[3]:
m = re.search(r'\bvarname\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)', line)
if m:
return m.group(1)
abc = 100
print(varname(abc))#abc
print(type(varname(abc)))#<class 'str'>
a,*b,c=[1,2,3,4,5]
print(a)
print(b)
print(c)
# 1
# [2, 3, 4]
# 5
# 在这里*起的是打包的作用
#-----------------例1------------------------
def testArgs(*args):
print(args)
testArgs(1,2,3)
testArgs([1,2,3])
testArgs(*[1,2,3])#这里*的作用是拆包,列表将不再作为一个整体
# (1, 2, 3) 将1,2,3放到一个元组中,赋值给args
# ([1, 2, 3],) 将[1,2,3]作为一个整体,args是只有一个元素的元组
# (1, 2, 3)效果等同于testArgs(1,2,3)
def testKwargs(**kwargs):
print(kwargs)
#-----------------例2------------------------
my_dict=dict(name="Tom",age=19,country="China")
# 解释,如果采用下面的方式,把字典直接作为参数传递给**kwargs
# 则程序报错,因为这里需要的是一个命名参数,而实际传递的
# 是一个位置参数,内容为一个字典,如果需要将字典作为参数传递
# 给**kwargs,必须加上**进行拆包
# testKwargs(my_dict)
testKwargs(**my_dict)
#-------------------例3----------------------
def test(name,age):
print(name,age)
# 此处**将字典拆包为命名参数
my_dict={"name":"Tom","age":18}
test(**my_dict)
# 程序输出
# Tom 18
#-----------------结论------------------------
# 在作为函数实参传递时,列表和字典对象都只作为一个单独的参数传递
# 在列表(元组)前面使用*,在字典前面使用**,都会进行拆分
# *会将列表(元组)拆分为多个位置参数
# **会将字典拆分为多个命名参数
# 函数形参声明中的*和**,与外界调用时实参前使用的*和**,作用不同
# 不要混淆
def test02(*args,**kwargs):
print(args)
print(kwargs)
def test01(*args,**kwargs):
# 解释1:*args,**kwargs为可变参数,python解释器
# 会将外界所有传入的参数放到args和kwargs两个变量中
# 从下面的print语句可以看出,args是一个元组
# kwargs是一个字典
print(args) #(1, 2, 3)
print(kwargs) #{'m': 10, 'n': 20}
# 解释2:当我们将args和kwargs直接传递给test02时
# test02会将这一个元组,一个字典作为两个参数
# 赋值给test02的args,而kwargs为空.
test02(args,kwargs)
# ((1, 2, 3), {'m': 10, 'n': 20})
# {}
# 解释3:当我们将*args,**kwargs传递给test02时
# 实际上是将外界调用的参数原封不动的传递给test02
# 因此输出的结果当然为一个元组,一个字典
test02(*args,**kwargs)
# (1, 2, 3)
# {'m': 10, 'n': 20}
test01(1,2,3,m=10,n=20)
# 结论,在使用可变参数的函数中,如果要将传入参数原封不动的传递
# 给另外一个函数,需要加上*和**。否则传递过去的是一个元组或字典
# 这里加上的*和**,实际上是起的拆包的作用,将元组和字典分别拆分
# 成多个位置参数和命名参数
标签:-- 注释 不同 spec 另一个 关键字 嵌套 简单 作用
原文地址:https://www.cnblogs.com/good18/p/11883094.html