1. c1.py
# 通过字典映射的关系,来模拟switch功能
# 不建议使用下标的方式,强烈推荐使用get方法
# 推荐使用函数式编程,字典的键值也可以为一个函数,推荐使用
# 当使用函数方式,需要让函数执行,调用方法后应该加一个括号;
# 此时使用的默认值也不能直接使用字符串了,字符串后加括号会报错,
# 思路一 (通过判断返回值的类型,执行对应方式方法)
# 将执行get的返回用一个变量接住,判断这个变量的类型,
# 数据类型如果是字符串直接返回,如果为函数则执行该方法,也可以起到容错作用,但这样比较麻烦,最好在定义时统一最好
# 思路二 (统一默认值和返回值都是函数形式) (推荐)
# 将返回默认值也改为函数形式,这时返回的结果都是方法了,都能执行
# 例如:模拟星期对应
# 普通方式
switcher = {
0 : 'Sunday',
1 : 'Monday',
2 : 'Tuesday',
3 : 'Wednesday',
4 : 'Thursday',
5 : 'Friday',
6 : 'Saturday'
}
day = 7
# print(switcher[day])
# 这种通过下标访问的方式会存在一些问题,当下标不存在时会报错
# 比较建议使用get方法
# get需要传递两个参数:第一个day参数,第二个默认值(在找不到时,会返回默认值)
print(switcher.get(day,'None'))
# 函数方式
def sunday():
return 'Sunday'
def monday():
return 'Monday'
def tuesday():
return 'Tuesday'
switcher1 = {
0 : sunday,
1 : monday,
2 : tuesday
}
day1 = 2
print(switcher1.get(day1,'None')())
# 在定义时统一默认值和返回值的类型 (此法甚好)
def sunday2():
return 'Sunday'
def monday2():
return 'Monday'
def tuesday2():
return 'Tuesday'
def default_value():
return 'None'
switcher2 = {
0 : sunday2,
1 : monday2,
2 : tuesday2
}
day2 = 2
print(switcher2.get(day2,default_value)())
2. c2.py
# 列表推导式
# 适用起来还是很方便的 (在其它的语言中map比较多,可能有些人使用map会比较熟悉)
# 但在有些情况,使用列表推导式会特别好,例如:对大于5的做平方,小于5的不用管
# 对于set数据类型,也可使用列表推导式,如果列表推导式用的'[]'返回结果是list(列表)类型;如果列表推导式用的'{}'返回结果是set(集合)类型;
# 求一组数的平方
a = [1,2,3,4,5,6,7,8]
# 如果不适用列表推导式,可以有两种方法:1.for循环;2.map
# 1.for循环
# for i in a:
# print(i*i)
# 2.map函数
# (1)有名函数
# def sqr(i):
# return i*i
# b1 = map(sqr,a)
# print(b1) #<map object at 0x00000000021BF470>
# print(list(b1)) #[1, 4, 9, 16, 25, 36, 49, 64]
# (2)匿名函数
# b2 = map(lambda x:x*x, a)
# print(b2) #<map object at 0x00000000026DF438>
# print(list(b2)) #[1, 4, 9, 16, 25, 36, 49, 64]
# 3.列表推导式
# (1)平方的方式一
# b3 = [i*i for i in a]
# print(b3)
# (2)平方的方式二
# b4 = [i**2 for i in a]
# print(b4)
# 4.对大于5的做平方,小于5的不用管
# b4 = [i*i for i in a if i>=5]
# print(b4) #[25, 36, 49, 64]
# 5.如果数据是set也可
a1 = {1,2,3,4,5,6,7,8}
b5 = [i**2 for i in a1 if i>=5] #外边包裹[],导致返回结果数据类型不一样
print(b5) #[25, 36, 49, 64]
b6 = {i**2 for i in a1 if i>=5} #外表包裹{},导致返回结果数据类型不一样
print(b6) #{64, 25, 36, 49}
3. c3.py
# 对于字典的列表推导式的写法
students = {
'石敢当' : 13,
'喜小乐' : 11,
'王小五' : 15
}
# 1.将所有的key提取出来
# 注意点:students是一个dic(字典),直接拿key和value是拿不到的,须要使用dic的items方法
# (1)直接拿不到,会报错
# a1 = [key for key,value in students]
# print(a1)
# (2)使用items方法
# a2 = [key for key,value in students.items()]
# print(a2) #['石敢当', '喜小乐', '王小五']
# 2.将key和value进行替换顺序 (此时是字典类型,推导式外层也须写为'{}'而非'[]')
# a3 = {value:key for key,value in students.items()}
# print(a3) #{13: '石敢当', 11: '喜小乐', 15: '王小五'}
# 3.元组,也可以使用处理一些数据,但不推荐使用
# a4 = (key for key,value in students.items())
# print(a4) # <generator object <genexpr> at 0x0000000001E11570> 返回的是一个generator对象
# 对这个generator对象进行遍历
# for i in a4:
# print(i)
4. c4.py
# 列表、元组、集合
# 可迭代对象、迭代器
# 可迭代的对象不一定是迭代器 (例如:列表、元组 就不是迭代器)
# 迭代器 一定是 可迭代对象
# 可迭代对象(iterable):能被for in遍历的对象都是可迭代对象 (例如:列表、元组、集合)
# 不可以 使用next函数进行遍历
# 列表和元组,不论循环几次都会打印几次
# 迭代器(iterator):首先是一个对象 class 自己定义的一个普通的class不能被for in遍历,但变成迭代器后就可了
# 可以 使用next函数进行遍历
# 迭代器 只能使用 一次 for in遍历,第二次就不执行了 (例如:执行两次for循环打印,值执行一次)
# 如果想多次打印:方案一:多次实例化,分别打印;方案二:进行拷贝(拷贝分深拷贝deepcopy和浅拷贝copy),打印拷贝的
# 普通对象可以变为迭代器
# 增加两个函数(__iter__,__next__),只要增加了这两个函数,就变成了迭代器
# 当每次调用for in 循环的时候都会调用一次__next__函数,所以须在__next__函数返回一个数据,当调用结束没有数据返回,就得在__next__中抛出一个异常
class BookCollection:
def __init__(self):
self.data = ['《往事》','《只能》','《回味》']
self.cur = 0
def __iter__(self):
# 需要返回自身
return self
def __next__(self):
# 当遍历完成,需要抛出一个异常 ( raise StopIteration() )
if self.cur >= len(self.data):
raise StopIteration()
r = self.data[self.cur]
self.cur += 1
return r
books = BookCollection()
# 方式一:通过for in 来遍历
# for i in books:
# print(i)
# 可以试一下,只打印一次哦
# for i in books:
# print(i)
# 方式二:通过next函数 (next只能对迭代器使用,不能对列表使用)
# print(next(books))
# print(next(books))
# print(next(books))
# 多次打印
# books1 = BookCollection()
# books2 = BookCollection()
# for i in books1:
# print(i)
# for i in books2:
# print(i)
# 深浅拷贝
# 先引入 copy
import copy
books3 = BookCollection()
# (1)浅拷贝
# books4 = copy.copy(books3)
# for i in books3:
# print(i)
# for i in books4:
# print(i)
# (2)深拷贝
# books5 = copy.deepcopy(books3)
# for i in books5:
# print(i)
5. c5.py
# 生成器
# print 0-10000
# 方案一:列表推导式
# 有缺点:非常消耗计算机的资源(内存)
# n是一个列表,消耗内存
n = [i for i in range(0,10001)]
# print(n)
# for i in n:
# print(i)
# 这里用生成器(generator)
# 只是一个算法,不会过度占用资源
# 虽然不会导致性能问题,但内部直接打印,没有什么意义 (一般会拿到值,在外部做一些操作)
# 此时,会想着直接return,但如果用了return,语法检测会报错;要将return改为yield关键字
# 生成器(generator)可以使用next方法调用,或者使用for循环
# 生成器的优势:既保证了函数的通用性,也保证了性能问题
# 生成器的内部没有保存数据,保存的是一个算法
# 列表推导式外层的'[]'改为'()'那就变为生成器
# def max1(x):
# y1 = 0
# while y1 <= x:
# print(y1)
# y1 += 1
# max1(10000)
# 返回一个值
def max2(x):
y2 = 0
while y2 <= x:
y2 += 1
# return 会报语法错误
# return y2
yield y2
# 此时得到的是一个 generator 对象 (generator:就是一个生成器)
# print(max2(10000)) #<generator object max2 at 0x0000000002161570>
# (1)next方法调用
# g = max2(10000)
# print(next(g))
# print(next(g))
# (2)for循环调用
# for i in max2(10000):
# print(i)
# 列表推导式外层的[]和()不同
# n1 = [i for i in range(0,10001)] #list形式,消耗内存资源
# n2 = (i for i in range(0,10001)) #<generator object <genexpr> at 0x0000000002141570> generator:生成器
# print(n1)
# print(n2)
# yield 关键字
# return 会返回,函数中执行return时,return后边的语句都不执行
# yield 会保存上次的结果,当执行next后继续执行时,不会终止后续的执行
6. c6.py
# None
# python中的'None'和其它的语言中的none不同
# None 不会代表 空字符串、空列表、0、False
# 空字符串、空列表、0、False 的 类型、取值和None都不同
# 判空时,结果有不同 (最后边的例子)
# 当a1为None时返回结果相同
# 但当a1为空时,返回就不同了
# 所以在判断是否为空时,强烈推荐使用: (1)if not a (2)if a 这两种方式比较稳妥哦! (当a='',a=[],a=False时都能得到想要的结果)
# None 和False
# 数据类型: None : NoneType类型; False:(布尔)bool类型
# 表示意义: None : 不存在; False:真假
# print(type(False))
a = ''
b = []
c = False
# print(a == None) #false
# print(b == None) #false
# print(c == None) #false
# print(a is None) #false
# print(type(None)) #<class 'NoneType'> None 的类型就直接为NoneType类型
# 判空时,结果有不同
def none_fun():
return None
# 这种写法,语法规范通不过,但能运行
# 当a1为None时返回结果相同
# 但当a1为空时,返回就不同了
# a1 = none_fun()
# a1 = []
# if not a1:
# print('S')
# else:
# print('F')
# if a1 is None:
# print('S')
# else:
# print('F')
7. c7.py
# (if a:) 和 (if None:) 走的分支一样,在Python中其它数据类型和bool存在一个对应的关系
# 对于自定义的类,如果内部没有嵌套方法和嵌套方法,返回的结果不同
# 如果类下边既没有定义 '__len__' 也没有定义 '__bool__' ,则返回真
# 类的返回真假和内部的两个函数相关 __len__,__bool__
# 当类的__bool__这个方法不存在时,类的返回结果由__len__决定;当两个都存在时,只受__bool__影响
# a = ''
# b = []
# c = False
# print(a == None) #false
# print(b == None) #false
# print(c == None) #false
class Test():
# 嵌套这个内置方法和不嵌套这个内置方法,返回结果不同哦
def __len__(self):
# 这里的返回只能是 正整数、0、bool(False,True)
# 0:整个类的返回结果为 False
# 其它正整数:整个类的返回结果为 True
# bool:True为True,False为False
# 字符串之类的,则非法了,这里本来就是len指长度,怎么能为str呢?
return 0
def __bool__(self):
# 这里的return只能是 bool(False,True),其它类型的数据都会报错
return False
pass
test = Test()
# 这里系统的len方法,会调用定义类里的__len__方法,如果对象中没有定义__len__方法,会报len方法不存在
print(len(test))
print(bool(test))
if test:
print('S')
else:
print('F')
8. c8.py
import time
from functools import wraps
# 函数添加装饰器,对函数本身产生的影响
# 不加装饰器,函数的name是函数的名;加了装饰器,函数name就改变了
# 不加装饰器,(通过help可以查看 print(help(f)) )函数名,注释都能获取;使用了装饰器,函数名改变了,当前函数的注释说明等也不能获取了,装饰器不能滥用
# 函数名改变不可取,Python中又提供了一个wraps装饰器,通过该装饰器可以保证名字不改变
# 引入wraps装饰器,在闭包函数上方使用装饰器即可,wraps装饰器可以接收参数,将原函数名当做装饰器的参数传入,就能实现使用了装饰器,原函数名不变
# 使用了装饰器wraps之后,原函数的信息没有被改变le
# 加装饰器,使用了闭包函数,相当于执行的是内部的wrapper函数,函数名等等信息就变成了内部wrapper函数的信息
# 通过装饰器函数 wraps 将原函数当做参数传入wraps中,从而实现了信息的替换,所以信息就没被改变了
def decorator(func):
@wraps(func)
def wrapper():
print(time.time())
func()
return wrapper
@decorator
def f():
'''
this is f funciton introduce
'''
print(f.__name__)
# f()
print(help(f))
(备注:以上内容来自七月老师的学习笔记,仅作为学习使用)