l1=[1,'s','china']
s1={'f',56}
d1={'name':'jack'}
len(s1)
#这个的作用就是让全部结果都显示出来。
%config ZMQInteractiveShell.ast_node_interactivity='all'
#函数定义与函数结构
def myfunc1(parm1,parm2='amazing'):
"\
here is document for this function\
multi lines \
"#__doc__ here
something=parm1
return str(something)+' is '+parm2
myfunc1
myfunc1('china')
输出结果为:
'china is amazing'
%whos
输出结果为:
Variable Type Data/Info
--------------------------------
d1 dict n=1
l1 list n=3
myfunc1 function
s1 set {'f', 56}
#Python 3.X新增加了一个特性(Feature),叫作函数注释 Function Annotations
#它的用途虽然不是语法级别的硬性要求,但是顾名思义,它可做为函数额外的注释来用
#Python中普通的函数定义如下:
def myfunc(parm1,parm2):
something=parm1
return str(something)+' is '+parm2
#添加了函数注释的函数会变成如下形式:
def myfunc1(parm1:'parm user given string to output',parm2:'this parm default value is amazing, user still can replace it'='amazing')-> 'function return should be a string':
"#__doc__ here"
something=parm1
return str(something)+' is '+parm2
myfunc1.__annotations__
#注释的一般规则是参数名后跟一个冒号,然后再跟一个expression,这个expression可以是任何形式。
#返回值的形式是用 “->” 描述
输出结果为:
{'parm1': 'parm user given string to output',
'parm2': 'this parm default value is amazing, user still can replace it',
'return': 'function return should be a string'}
def:运行期指令,以代码对象为参数创建函数实例,并在当前上下文中与指定的名字相关联
#def是运行期指令
import dis;
dis.dis(compile("def test():pass","","exec"))
#def的伪码
#test=make_function('test',code)#dis操作是在函数实例创建完成后针对__code__,而非针对创建过程
#以单个代码对象为模板创建多个函数实例
def make_func(n):
ret=[]
for i in range(n):
def test():print('hello',n)
print(id(test),id(test.__code__))
ret.append(test)
return ret
make_func(4)#不同实例,相同代码,也可以不同实例,不同代码(属性动态添加)
输出结果为:
4432203856 4432205264
4432206160 4432205264
4432384800 4432205264
4432385232 4432205264
[.test()>,
.test()>,
.test()>,
.test()>]
作用:为上下文提供调用实例,并管理所需的状态数据。负责管理运行期状态,如默认参数,动态添加的属性,由MAKE_FUNCTION指令创建
#探索PyFunctionOjbect
def test1(a,b,c=1):
str1='weijichen.cn'
print(c)
return b
'co_name',test1.__code__.co_name#函数名
'co_object',test1.__code__# PyCodeObject", line 1>
'co_code',test1.__code__.co_code#函数中的代码对象字节码(二进制存储)
'co_lnotab',test1.__code__.co_lnotab#'字节码的偏移值与对应的源码的行号的相对值'
'co_filename',test1.__code__.co_filename#函数所在文件名
'co_firstlineno',test1.__code__.co_firstlineno#函数在文件中的首行的行数1
'co_stacksize',test1.__code__.co_stacksize#占用了几个栈桢
Python中栈的分类:
用户栈:函数被调用时,会专门为其分配用户栈内存,用户栈内存除用来存储变量外,还包括字节码参数和返回值所需空间。
系统栈:用于机器执行,用户栈用于代码执行状态。
Python中栈的作用:
栈用于指令执行,与线程绑定。函数调用与执行都依赖于线程栈上存储的上下文和执行状态。
import dis
def test(a,b):
c=a+b
return c
dis.dis(test)
2 0 LOAD_FAST 0 (a) #从Fast读取参数a,压入用户栈
2 LOAD_FAST 1 (b)#从Fast读取参数b,压入用户栈
4 BINARY_ADD #系统指令从用户栈读取操作数,执行加法操作
6 STORE_FAST 2 (c)#结果写回Fast
3 8 LOAD_FAST 2 (c)
10 RETURN_VALUE
栈帧(Stack Frame)
线程栈这块内存中,每个被调用函数都分配着一块区域
Call stack是函数调用堆栈(运行时函数的调用过程),除返回地址,还有为函数提供参数,局部变量存储空间等
调用函数时的内存变化:
函数每次调用,都会新建栈帧,用于局部变量和执行过程存储。执行完成后,栈帧内存被回收,同时释放相关对象。
def test():
return id(locals())
print(test())#Create New StackFrame
print(test())#Create Another New StackFrame
输出结果为:
2439859900488
2439859902432
查看栈帧对象PyFrameObject
PyFrameObject,栈帧表示程序运行时函数调用栈中的某一帧。函数没有属性可以获取它,因为它在函数调用时才会产生
想要获得某个函数相关的栈帧,则必须在调用这个函数且这个函数尚未返回时获取。
sys._getframe()方法可以获取当前栈帧
_back: 调用栈的前一帧
f_code: 栈帧对应的code对象
f_locals: 用在当前栈帧时与内建函数locals()相同,但你可以先获取其他帧然后使用这个属性获取那个帧的locals()
f_globals: 用在当前栈帧时与内建函数globals()相同,但你可以先获取其他帧……
f_builtins -> dict key: python的内置函数名
import sys
def func():
frame = sys._getframe()
print(frame.f_locals)
print(frame.f_globals)
print(frame.f_back.f_locals)
#你可以打印frame的各个域
print(s)
func()
import sys
value = 3
def A():
frame = sys._getframe()
print ('current function is : ', frame.f_code.co_name)
caller = frame.f_back
print ('caller function is : ', caller.f_code.co_name)
print ("caller's local namespace : ", caller.f_locals)
print ("caller's global namespace : ",caller.f_globals.keys())
def B():
a = 1
b = 2
print('------')
A()
print('------')
B()
cf=sys._current_frames()
import sys,dis
def A():
x='func A'
B()
def B():
C()
def C():
c_var='test'
f=sys._getframe(0)#向上2级,获取A栈帧,1获取B,0是当前
print('frame及遍历---------------------------------------------------------------')
print(f.f_code.co_name,'栈帧类型和对象:',type(f),f)
# print('遍历:',dir(f))
print('名字空间---------------------------------------------------------------')
# print('函数所在模块的的名字空间f_globalsa或直接globals():',f.f_globals)#返回函数所在模块的的名字空间
# print('frame f_builtins:',f.f_builtins)#A人
print(f.f_code.co_name,'名字空间f_locals(运行期):',f.f_locals)#A名字空间(运行期)
print('代码对象---------------------------------------------------------------')
print(f.f_code.co_name,'代码对象f_code:',f.f_code)#A代码对象
print(f.f_code.co_name,'代码对象f_fileno:',f.f_lineno)#所在文件行数
print(f.f_code.co_name,'最后执行指令的偏移量f_lasti:',f.f_lasti)#A最后执行指令的偏移量
print('栈帧对象---------------------------------------------------------------')
print(f.f_code.co_name,' frame f_back:',f.f_back)#前一帧对象
print(f.f_code.co_name,' frame f_trace:',f.f_trace)#trace对象
print('f_code,---------------------------------------------------------------')
print('该f_code即为对应函数的代码对象-------------------------')
# print('遍历f_code:',dir(f.f_code))
print('co_stacksize',f.f_code.co_stacksize)
A()
返回所有栈帧
sys._current_frames()#返回一个dict对象
import sys
sys._current_frames()#返回一个dict
输出结果为:
{6792: ,
7640: ,
9380: ,
10816: ,
13344: }
def myadd2(a,b):
return a+b
def myadd3(a,b,c):
return a+b+c
def myadd4(a,b,c,d):
print(d)
Python内置电池round函数的帮助中,出现了[, ndigits]这个东东。
其它的一些Python对象提供的方法中也有类似的东东出没,比如对序列对象进行切片访问时。
就是Python可选位置参数。
注意:这样的参数是无法通过自定义函数来创建的。只有Python中的内置函数可以。
Help on built-in function round in module builtins:
round(...)
round(number[, ndigits]) -> number
Round a number to a given precision in decimal digits (default 0 digits).
This returns an int when called with one argument, otherwise the
same type as the number. ndigits may be negative.
#关键字参数,与不定长关键字参数
def myadd0(args,lastnum=1000):
return args+lastnum
myadd0(7)
def myadd(parm1,parm2=500):
print(parm1+parm2)
def myadd(parm1,parm2=500,parm3=5):
print(parm1+parm2)
myadd?
from inspect import signature# 注意是小写的signature
def func(parm1,parm2='kw'):
return parm1
def func(parm1):
pass
# 获取函数签名
func_sig = signature(func)
# 通过函数签名的parameters属性,可以获取函数参数
func_params = func_sig.parameters
func_params
#或者直接使用ipython下的?
输出结果为:
mappingproxy({'parm1': })
__code__
对象下的反映def test1(a,b,c=1):
str1='julyedu.com'
return b
'co_argcount',test1.__code__.co_argcount#位置参数的个数,而co_nlocals是局部变量数目,包括位置参数在内。
'co_nlocals&co_varnames',test1.__code__.co_nlocals,test1.__code__.co_varnames#多少个局部变量,以及及变量的名字。
'符号名集合co_names',test1.__code__.co_names #符号名集合
'常量集合co_const',test1.__code__.co_consts #常量集合
# 位置参数,键(关键字)参数,*args扩展位置参数[元组对象]和**kwargs扩展键(关键字)参数[字典]。
# 位置参数还能设置默认值,如果有默认值,默认值是在MAKE_FUNCTION指令赋值给`funcname.__defaults__`的。
'co_flags',test1.__code__.co_flags
# 【1】function没有args或*kw时,`funcname.__code__.co_flags=67`;
# 【2】function有args没有*kw时,funcname.__code__.co_flags=71;
# 【3】function没有args有*kw时,funcname.__code__.co_flags=75;
# 【4】function既有args也有*kw时,funcname.__code__.co_flags=79;
# 【5】function是一个generator时,funcname.__code__.co_flags=99.
#对于像 def f(a, b, *lst):这样的函数,如果调用函数时参数为f(1,2,3,4),其实在PyCodeObject对象中的co_argcount=2, co_nlocals=3。
输出结果为:
('co_argcount', 3)
('co_nlocals&co_varnames', 4, ('a', 'b', 'c', 'str1'))
('符号名集合co_names', ())
('常量集合co_const', (None, 'julyedu.com'))
('co_flags', 67)
##函数对象参数的默认值存放在函数对象的,__defaults__属性中,是一个Tuple类对象
#字节数换算为KB,MB,GB,TB
def CaluSize(bytesize,trans='KB'):
if trans=='KB':size=1024
if trans=='MB':size=1024**2
if trans=='GB':size=1024**3
if trans=='TB':size=1024**4
return str(bytesize//size)+trans
CaluSize.__defaults__
CaluSize.__defaults__=('TB',)
CaluSize.__defaults__
CaluSize(110241550654651654544)
输出结果为:
('KB',)
('TB',)
'100264106TB'
##函数对象属性
##函数对象属性值存放在函数对象的,__dict__属性中,是一个Dict类对象
CaluSize
CaluSize.__dict__
CaluSize.__dict__['new_atrr']='test'
CaluSize.__dict__
输出结果为:
{'new_atrr': 'test'}
#函数返回值
#有返回值 与无返回值(即使没有return语句,依旧会return一个NoneType类的对象None)
def myadd(a):
return a,5
def myadd1(a,b,c,d):
print(a+b+c+d)
def myadd2(a,b):
pass
def myadd1(a,b,c,d,*parms):
print(type(parms))
print('parms:',parms)
print('a,b,c,d:',a,b,c,d)
return sum(parms)
myadd1(1,2,3,4,5,6)
def myadd2(arg,*args):
print(type(args))
print(args)
return sum(args)
myadd2(18,1,2,3)
def myadd3(arg,*args):
print(type(args))
print(args)
return sum(args)
myadd3(18,1,2,3)
输出结果为:
parms: (5, 6)
a,b,c,d: 1 2 3 4
11
(1, 2, 3)
6
(1, 2, 3)
6
def myadd(**kwargs):
print(kwargs)
myadd(add='sh',tel=13333,name='jack',height=178)
myadd(address='sh',cellphone=13333,)
def myaddkw(**names):
print(type(names))
print(list(names.values()))
return list(names.values())
myaddkw(name='david',gender='male',age=0)
myadd0(args=5, lastnum=6)
l1=[1,2,3,4,5,6]
a,b,c,d,e,f=l1
f
l1=[1,2,3,4,5,6]
a,b,*c,d,e=l1
a,b,c,d,e
def myfun1(*args,**kwargs):
print(args)
for item in kwargs:
print(item)
d1={'name':'david','add':'bj','date':'2018-8-1'}
l1=[1,2,3,4,5,6,7]
myfun1(*l1,**d1)
输出结果为:
(1, 2, 3, 4, 5, 6, 7)
name
add
date
/
与*
sorted?
l1=['China','Japan','UK','Beijing']
#Signature: sorted(iterable, /, *, key=None, reverse=False)
#参数/是指,iterable这个参数只能以位置参数形式给,不能以关键字参数形式给,否则报错
#这类参数只能在C API中被指定,def定义会报错
#正常
sorted(l1)
#报错
#sorted(iterable=l1)#TypeError: Function takes at least 1 positional arguments (0 given)
#参数*是指,key这个参数只能以关键字参数形式给,不能以位置参数形式给,以否则报错
#这类参数可以自行定义
#正常
sorted(l1,key=lambda x:(x[-2]))
#报错
# sorted(l1,lambda x:(x[-1]))#TypeError: must use keyword argument for key function
输出结果为:
['Beijing', 'China', 'Japan', 'UK']
['UK', 'Japan', 'China', 'Beijing']
#偏函数,固定了部分参数的函数
import functools
a=0x24
a
int(str(a),base=32)
hex2int=functools.partial(int,base=16)
type(hex2int)
hex2int(str(a))
def mysal(nums,rate=6.95):
return nums*rate
mysal(5000)
mysal(12000)
import functools
rmb2eur=functools.partial(mysal,rate=1.01)
rmb2jpn=functools.partial(mysal,rate=82)
rmb2jpn(5000)
def a():
f=15
print(locals())
a()
f
# exec?
# Signature: exec(source, globals=None, locals=None, /)
# Docstring:
# Execute the given source in the context of globals and locals.
#要exec的python源码
ns={}#传入的容器是空的
exec('def inside_func():pass',ns)
ns['inside_func']#返回的窗器是带有结果的,也就是说传入名字空间被改变了
s='''
def test():
print(hex(id(locals())),__name__)
#exec的代码是以builtins模块下进行运行的
test()
'''
g={'g':666}#传给s的全局名字空间
print('入口程序模块:',hex(id(ns)),__name__)
exec(s,g)
%whos
输出结果为:
入口程序模块: 0x23813168ea0 __main__
0x238130b84c8 builtins
Variable Type Data/Info
----------------------------
g dict n=3
l dict n=2
ns dict n=2
s str \ndef test():\n print(<...>ltins模块下进行运行的\n\ntest()\n
#eavl,显示传入容器对象做为动态代码的专用名字空间
# Signature: eval(source, globals=None, locals=None, /)
# Docstring:
# Evaluate the given source in the context of globals and locals.
g={"x":100}
l={"y":101}
eval("x+y",g,l)
输出结果为:
201
def fib(n):
a,b=0,1
for i in range(n):
a,b=b,a+b
return a
fib(3)
def sdd(a,b,c):
arr=[a,b,c]
arr.sort()# -- 排序规则,reverse = True 降序, reverse = False 升序(默认)
#arr.sort(reverse=True)
return arr
sdd(2,3,1)
def calc(*num):
return num
calc(1,2,3,4)
def funcd(classname,*classfeatures,**classmates):
print("班级名:%s"%classname)
print("班级特色:%s"%str(classfeatures))
totalage=0
myclassmates=[]
for (key,value) in classmates.items():
totalage=totalage+value
myclassmates.append(key)
print("班级成员:%s"%str(myclassmates))
print("平均年龄:%s"%str(totalage/len(classmates)))
classmates={"zhangsan":15,"lisi":20}
classfeatures=["勤奋","颜值高"]
funcd("高三1班",*classfeatures,**classmates)
班级名:高三1班
班级特色:('勤奋', '颜值高')
班级成员:['zhangsan', 'lisi']
平均年龄:17.5
身体质量指数(BMI)是根据人的体重和身高计算得出的一个数字,BMI是可靠的身体肥胖指标,其计算公式:BMI=Weight/High2,其中体重单位为公斤,身高单位为米。
计算公式为: B M I = 体 重 ( k g ) ÷ 身 高 2 ( m ) BMI=体重(kg)÷身高^2(m) BMI=体重(kg)÷身高2(m)
提示用户输入体重(kg)和身高的数字(m)(注意单位),然后计算BMI。
根据BMI指数范围,定义当前健康状态。BMI指数在18至25之间定义为健康的标准体重,小于该范围定义为偏瘦,超过该范围定义为偏重。
将BMI指数和其所代表状态输出
def bmicheck(height,weight):
bmi=weight/pow(height,2)
if bmi < 18:
print("BMI指数是:"+str(bmi)+",健康为偏廋")
elif bmi < 25:
print("BMI指数是:"+str(bmi)+",健康为标准")
else:
print("BMI指数是:"+str(bmi)+",健康为偏重")
bmicheck(1.80,60)
BMI指数是:18.51851851851852,健康为标准