python自己添加了些全局变量
print(vars())
"""
结果:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00795650>,
'__spec__': None,
'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'C:/Users/Sullivan/PycharmProjects/q1/day12/global.py',
'__cached__': None}
"""
这些全局变量的作用
#__doc__ 包含py文件的注释,文件的注释在——文件内容的最上面用三引号引起来
print(__doc__)#__file__ 包含当前文件的路径
print(__file__)#__package__ 对于单读文件的package是没有意义的,代表当前的py文件在哪几个文件夹下
print(__package__)#当前文件没有,会返回None
from day2 import homework
print(homework.__package__) #文件夹套文件夹时用点"."区分
#结果:day2#__cached__ 缓存,对于py文件是可以设置一个缓存的,python2里没有,了解即可
print(__cached__)#当前文件也有,会返回None
from day2 import homework
print(homework.__cached__)
#结果:C:UsersSullivanPycharmProjectsq1day2__pycache__homework.cpython-36.pyc#__name__ 如果当前执行的是当前文件,它的__name__就是__main__,其它的不管是导入还是其它的操作__name__就是文件名
print(__name__)
#结果__main__
from day2 import homework
print(homework.__name__)
#结果:day2.homework#__builtins__ 里边放的就是内置函数#__loader__和__spec__ 都是p3中新加的
# 因为程序的入口文件就是用户当前执行的文件,所以以后写主程序文件的时候 if __name__ == "__main__":execute()#防止其他文件导入该文件时,执行主函数name的实际应用
#利用sys,os模块和__file__变量,把路径添加到system path中import os,sys p1 = os.path.dirname(__file__) #获取当前路径 p2 = "bin" my_dir = os.path.join(p1,p2) #字符串拼接,拼接出新路径 sys.path.append(my_dir) #添加到system path里面file的实际应用
Python参数传递 有引用传递&值传递两种
值传递:方法调用时,实际参数把它的值传递给对应的形式参数,方法执行中形式参数值的改变不影响实际参数的值。
a1 = 520
a2 = a1
print(a1,a2)
结果:520 520
a2 = a1 + 1
print(a1,a2)
结果:520 521
引用传递:也称地址传递,在方法调用时,实际上是把参数的引用(传的是地址,而不是参数的值)传递给方法中对应的形式参数,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,方法执行中形式参数值的改变将会影响实际参数的值。
a1 = [1,2]
a2 = a1
a2.append(3)
print(a1)
结果:[1, 2, 3]
print(a2)
结果:[1, 2, 3]
在Python中,数字、字符或者元组等不可变对象类型都属于值传递,而字典dict或者列表list等可变对象类型属于引用传递。
如果要想修改新赋值后原对象不变,则需要用到python的copy模块,即对象拷贝。对象拷贝又包含浅拷贝和深拷贝。下面用例子来说明
例一
import copy
l1 = [[1, 2], 3]l2 = py(l1)
l2.append(4) #因为浅拷贝之拷贝第一层,所以对第一层操作不会影响l1
l2[0].append(5) #因为浅拷贝只拷贝的第一层,所以对第二层的操作还是值传递,所以l1和l2中都有列表的第一个元素都会添加一个5
print(l1)
print(l2)
结果:
[[1, 2, 5], 3]
[[1, 2, 5], 3, 4]
例二
l1 = [[1, 2], 3]
l3 = copy.deepcopy(l1)l3[0].append(6)
print(l1)
print(l3) #深拷贝全部拷贝,所以只是l3的值变了,l1并没有改变
# 结果:
[[1, 2], 3]
[[1, 2, 6], 3]
从上例可以看出py属于浅拷贝,拷贝的是第一层list,而copy.deepcopy属于深拷贝,对list所有子元素都进行深拷贝。
Python的字符串格式化有两种方式: 百分号方式、format方式
百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存。
%[(name)][flags][width].[precision]typecode
注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式
功能示例:
# %[(name)][flags][width].[precision]typecodes = ["i am %s,age %d" % ('ciri',18)]
# (name)
s = "i am %(n1)s,age %(n2)d" % {"n1":"ciri","n2":16}
s = "i am %(n1)s,age %(n1)s" % {"n1":"ciri"} #也可以两个共用一个值#flags和width一般放到一起用,一般用不到
#字符
s = "i am %(n1)+10s ellie" % {"n1":"ciri"}
s = "i am %(n1)-10s ellie" % {"n1":"ciri"}
s = "i am %(n1) 10s ellie" % {"n1":"ciri"}
s = "i am %(n1)010s ellie" % {"n1":"ciri"}
#数字
s = "age %(n2)+10d ellie" % {"n2":16}
s = "age %(n2)+10d ellie" % {"n2":-16}s = "age %(n2)-10d ellie" % {"n2":16}
s = "age %(n2)-10d ellie" % {"n2":-16}s = "age %(n2) 10d ellie" % {"n2":16}
s = "age %(n2) 10d ellie" % {"n2":-16}s = "age %(n2)010d ellie" % {"n2":16}
s = "age %(n2)010d ellie" % {"n2":-16}#precision——默认输出6位小数
s = "age %f ellie" % 1.2
s = "age %.2f ellie" % 1.2 #指定小数保留几位
常用格式化:
tpl = "i am %s" % "alex"tpl = "i am %s age %d" % ("alex", 18)tpl = "i am %(name)s age %(age)d" % {"name": "alex", "age": 18}tpl = "percent %.2f" % 99.97623tpl = "i am %(pp).2f" % {"pp": 123.425556, }tpl = "i am %.2f %%" % {"pp": 123.425556, }
[[fill]align][sign][#][0][width][,][.precision][type]
都是中括号[],所以参数都可以省略
常用格式化:
# [[fill]align][sign][#][0][width][,][.precision][type]tpl = "i am {}, age {}".format("seven", 18)
tpl = "i am {}, age {}".format(*["seven", 18,'ciri']) #传入列表,列表的元素可以比前面的内容所
#可以传索引
tpl = "i am {0}, age {1}".format("seven", 18)
tpl = "i am {0}, age {1}".format(*["seven", 18])
#通过name获取
tpl = "i am {name}, age {age}".format(name="seven", age=18)
tpl = "i am {name}, age {age}".format(**{"name": "seven", "age": 18})#传字典要穿加上**
#第一个0表示拿第几个元素
tpl = "i am {0[0]}, age {0[1]}".format([1, 2, 3], [11, 22, 33])
#分别接收字符串、数字和浮点数
tpl = "i am {:s}, age {:d}, money {:f}".format("seven", 18, 88888.1)
tpl = "i am {:s}, age {:d}".format(*["seven", 18])tpl = "i am {name:s}, age {age:d}".format(name="seven", age=18)
tpl = "i am {name:s}, age {age:d}".format(**{"name": "seven", "age": 18})tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)
tpl = "numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}".format(15)
tpl = "numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}".format(num=15)
# 先到 for x in range(10) 取元素,再把取出来的元素按照 前面的内容(x,x+1,x*2) 进行操作,然后把结果依次放到列表中
a = [x for x in range(10)]
print(a)
a = [x+1 for x in range(10)]
print(a)
a = [x*2 for x in range(10)]
print(a)
结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10
赋值一种方法
t = ('ciri',8)
a,b = t #值和变量的个数要相同,否则会报错print(a)
print(b)
结果:
ciri
8
方法一:小括号的方式
#把列表生成式的中括号,改成小括号,就变成了一个生成器
s = (x for x in range(10))
print(s)# <generator object <genexpr> at 0x03726360>
#输出的是一个生成器对象,所有的值压根就没有被创建出来(重点)
之前的列表生成式生成了10个值,就相当于10盘菜,已经做出来了,想什么时候成就什么时候吃,想什么时候调动就什么时候调用,想吃第几道就吃第几道。
生成器就相当于,厨师脑子里的10道菜,想吃的时候才做出来,你不吃就不会做出来,只能按顺序吃(8,9),不能隔着吃,也不能倒着吃
方法二:yield方式
def func():print('ok')yield 1print('ok2')yield 2print(func) # <function func at 0x03163540> 可以看出func还是一个函数func() #不会执行函数,此时func()是一个生成器对象print(func())
# <generator object func at 0x034764B0> 可以看出 func加上括号() 是一个生成器对象
yield的执行过程
def func():print('ok')yield 1print('ok2')yield 2next(func())
next(func())
结果:
ok
ok2for i in func():print(i)
结果:
ok
1
ok2
2
s = (x for x in range(10))
print(s)# 方法一:
print(s.__next__())#内部特殊的方法,不建议用# 方法二:
#python3中新加的方法
print(next(s)) #以后就用这种方法# 方法三:
#python2中可以直接调用next方法
)# 方法四:
for i in s:print(i)#for就是内部调用next方法
def fib(max):n,b,a = 0,0,1while n<max:print(b) #最开始的值yield bb, a = a, b + a #会先把b+a计算出来n = n + 1g = fib(8)
next(g)
next(g)
next(g)
next(g)
b, a = a, b + a为什么这个可以,把a的值赋值给b,b+a的值赋值给ab = a a = b + a 这个不行#因为b, a = a, b + a会先计算出来b+a的值补充:b, a = a, b + a为什么这个可以
send和next的区别就是,send可以给yield前面的变量传值
def bar():print('ok')count = yield 1print(count) #第二次进来,就会直接把send的值,直接传给yield前的参数countyield 2b = bar()#b.send('ciri') 会报错,因为第一次进来,执行到到yield就冻结了,出去了,所以第一次不知道给谁赋值,所以就不能用send传参数ret1 = b.send(None) #用send第一次进入时,只能这么写,等价于next(b)
print(ret1) #结果 1ret2 = b.send('ciri')
print(ret2) #结果:2
#做和吃是同时发生的
import timedef consumer(name):print("%s 准备吃包子啦!" % name)while True:baozi = yieldprint("包子[%s]来了,被[%s]吃了!" %(baozi,name))def producer(name):c = consumer('A')c2 = consumer('B')next(c)next(c2)print("老子开始准备做包子了")for i in range(10):time.sleep(1)print("做了2个包子")c.send(i)c2.send(i)
producer("ciri")
生成器都是迭代器,迭代器不一定是生成器
如何创建一个迭代器?
#iter方法就做一件事情,返回了一个迭代器对象li = [1,2,3,4]
d = iter(li)
print(d)
# <list_iterator object at 0x034A4770> iterator迭代器,iterable可迭代对象
什么是迭代器?
满足两个条件:1.有iter方法 2.有next方法
for循环后面加的是什么?
可迭代对象
什么是可迭代对象?
现象上——能进行 for循环的,都是可迭代对象
本质上——内部有iter方法的,就是可迭代对象
执行迭代器
li = [1,2,3,4]d = iter(li) #iter方法就做了一件事情,返回了一个迭代器对象print(next(d))
print(next(d))
补充:for循环 执行时的内部操作三件事
实例:操作文件
f = open(','r')
for i adlines(): #假如文件很大的话,会全部都放到内存中去pass
for i in f(): #这里的f就是一个可迭代对象,节省内存空间pass
练习:使用文件读取,找出文件中最长的行
max(len(x.strip()) for x in open('/hello/abc','r'))
Python的字符串格式化有两种方式: 百分号方式、format方式
百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存。
转载于:.html
本文发布于:2024-01-29 06:56:26,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170648258913505.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |