day4 内置函数 迭代器&生成器 yield总结 三元运算 闭包 __getattr__ __setattr__ __delattr__

内置函数:
  1 内置函数
  2 
  3 # abs()返回一个数字的绝对值。如果给出复数,返回值就是该复数的模。
  4 b = -100
  5 print(b)
  6 print(abs(b))
  7 
  8 
  9 # all() 所有为真才为真,只要有一个假就是假,判断假的条件--> 假: 0,None, 以及空值(“”(空字符串), [], (), {}),都为假,其他都为真
 10 # all(iterable), iterable -- 元组或列表。
 11 a = None
 12 b = []
 13 c = {}
 14 d = ()
 15 e = ""
 16 e1 = " "          # 空格是字符串,所以结果为True
 17 f = 0
 18 print(all([e1, f]))  # 输出 False
 19 
 20 print(bool(a), bool(b), bool(c), bool(d), bool(e), bool(e1), bool(f))
 21 # 输出(False, False, False, False, False, True, False)
 22 li = [1, 2, 3, "", False]
 23 l = [1, 2, 3, " "]
 24 print(all(li))  # 输出False
 25 print(all(l))   # 输出True
 26 
 27 # bool  判断真假
 28 val = False
 29 r = bool('False')
 30 r1 = bool(val)
 31 print(r)   # 输出 True
 32 print(r1)  # 输出 False
 33 # Python中除了''、""、0、()、[]、{}、None为False之外,其他的都是True。也就是说上面的'False'就是一个不为空的字符串,所以结果就为True了,将一个值转化成布尔值,使用标准的真值测试例程。如果x为假或者被忽略它返回False;否则它返回True。bool也是一个类,它是int的子类。bool不能被继承。它唯一的实例就是False和True。
 34 
 35 
 36 # any() 一个为真就为真  同all相反,只有有真就返回True  真: 非0 非None 非空
 37 li = [1, 2, 3, "", False]
 38 l = [1, 2, 3, " "]
 39 print(any(li))  # 输出True
 40 print(any(l))   # 输出True
 41 
 42 
 43 # ascii(),很少用到,ascii等同于repr函数   固定用法:ascii(对象)  ===去类中找 __repr__ 方法,获取返回值,自动去对象对应的类里面找_repr_方法
 44 class Foo(object):
 45     def __repr__(self):
 46         return "hello repr 中文"
 47 
 48 li = Foo()
 49 n = ascii(li)
 50 print(n)
 51 #输出:hello repr
 52 # 转义汉字字符
 53 r = ascii('哈哈')
 54 print(r)    # 输出'u54c8u54c8'
 55 
 56 
 57 # 进制转换:bin oct int hex   二进制  八进制  十进制  十六进制
 58 # 任意进制转10进制
 59 i = int('0b11', base=2)  # 0b可省略
 60 print(i)  # 输出:3
 61 
 62 i = int('11', base=8)
 63 print(i)    # 输出:9
 64 
 65 i = int('0x11', base=16)
 66 print(i)    # 输出:17
 67 
 68 # 十进制转换为其他进制
 69 r = oct(8)     # 十进制转8进制
 70 h = hex(14)     # 十进制转16进制
 71 print(r, h)    # 输出('010', '0xe')
 72 
 73 # 进制互转
 74 # bin() 可以将 八 十 十六 进制 转换成二进制
 75 print(bin(10), bin(0o13), bin(0x14))
 76 # oct() 可以将 二 十 十六 进制 转换为八进制
 77 print(oct(10), oct(0b101), oct(0x14))
 78 # int() 可以将 二 八 十六进制转换为十进制
 79 print(int(0o13), int(0b101), int(0x14))
 80 # hex() 可以将 二 八 十 进制转换为十六进制
 81 print(hex(0b101), hex(110), hex(0o12))
 82 
 83 
 84 # bytes字节 bytearray 字节列表
 85 bytes("xxxx", encoding="utf-8")
 86 bytearray([source[, encoding[, errors]]])
 87 # 返回一个新的字节数组。bytearray类型是一个可变的整数序列,整数范围为0 <= x < 256(即字节)。 它有可变序列的大多数方法,参见Mutable Sequence Types,同时它也有str类型的大多数方法,参见String Methods。
 88 举例:将字符串“杜拉拉”转换成UTF-8编码的字节类型  bytes('杜拉拉', encoding='utf-8')
 89 
 90 # chr ord 字符串、数字转换 
 91   c = chr(65) 
 92   i = ord("A")  
 93   print(c, i) # 输出('A', 65)  
 94 
 95 应用:生成验证码 
 96 import random
 97 verification_code = ''
 98 for i in range(6):
 99     rand = random.randrange(0, 4)
100     if rand == 3 or rand == 1: 
101        num = random.randint(0, 9)
102        verification_code += str(num)
103     else:
104        num = random.randint(65, 91)
105        letter = chr(num)
106        verification_code += letter
107 print(verification_code)
108 
109 
110 import random
111 verification_code = ''
112 for i in range(6):
113     rand = random.randrange(0, 6)
114     if i == rand:
115          num = random.randint(0, 9)
116          verification_code += str(num)
117     else:
118          num = random.randint(65, 91)
119          letter = chr(num)
120          verification_code += letter
121 print(verification_code)
122 
123 
124 # callable(object),检查某个对象是否可以被执行 即 对象() 
125 # 如果object参数可调用,返回True;否则返回False。如果返回真,对其调用仍有可能失败;但是如果返回假,对object的调用总是失败。注意类是可调用的(对类调用返回一个新实例);如果类实例有__call__()方法,则它们也是可调用的。 
126 def f1(): 
127     return 
128 r = callable(f1) # 判断f1()是否可执行 
129 print(r) 
130 
131 
132 # compile 编译 默认读文件都是字符串,经过编译变成python可执行的代码 
133 # 例子:
134 code = 'def hellocute():return "name %s ,age %d" %(name,data[0],) ' 
135 func = compile(code, '<string>', "exec") # 把上面的字符串编译为函数 
136 
137 # dir 显示类的方法  
138 如果没有参数,返回当前本地作用域内的名字列表。如果有参数,尝试返回参数所指明对象的合法属性的列表。 
139 >>> import struct 
140 >>> dir() # show the names in the module namespace 
141 ['__builtins__', '__doc__', '__name__', 'struct'] 
142 >>> dir(struct) # show the names in the struct module 
143 ['Struct', '__builtins__', '__doc__', '__file__', '__name__', 
144 '__package__', '_clearcache', 'calcsize', 'error', 'pack', 'pack_into', 
145 'unpack', 'unpack_from'] 
146 >>> class Shape(object): 
147 def __dir__(self): 
148 return ['area', 'perimeter', 'location'] 
149 >>> s = Shape() 
150 >>> dir(s) 153 ['area', 'perimeter', 'location'] 
151 
152 # divmod(10,3) 显示商和余数 
153 # 分页 :余数大于0 商+1 为页数 (分页:每页存放10条数据,一共101条数据,需要几页? divmod(101,10) 可知为11页才能存放101条数据) 
154 在长整数除法中,传入两个数字(非复数)作为参数,返回商和余数的二元组。 
155 对于混合的操作数类型,应用二元算术运算符的规则。对于普通整数或者长整数,结果等同于(a // b, a % b)。对于浮点数结果是(q, a % b),q一般是math.floor(a / b),但也可能比那小1。 
156 不管怎样,q * b + a % b非常接近于a,如果a % b非0,它和b符号相同且0 <= abs(a % b) < abs(b)。 
157 
158 # eval # 字符串 转算 执行表达式 结果放在返回值中,有返回值 
159 eval(expression[, globals[, locals]]) 
160 参数是Unicode或者Latin-1编码的字符串,全局变量和局部变量可选。如果有全局变量,globals必须是个字典。如果有局部变量,locals可以是任何映射类型对象。 
161 >>> x = 1 
162 >>> print eval('x+1') 
163 a = "1 + 3" 
164 n = eval(a) 
165 print(n) 
166 ret = eval("a+60", {"a": 88}) 
167 print(ret) 
168 
169 # exec: 执行py代码 
170 没有返回值,直接输出结果: 
171 exec("for i in range(3):print(i)") 
172 
173 
174 # globals() 获取所有的全局变量 
175 # local() #获取所有局部变量 
176 def f1(): 
177     name = 123 
178     print(locals()) # 输出123 
179     print(globals()) 
180 f1() 
181 
182 
183 # hash(对象) 计算获取对象hash值(长度固定) 内存优化 
184 # 返回对象的hash(哈希/散列)值(如果有的话)。hash值是整数。它被用于在字典查找时快速比较字典的键。相同的数值有相同的hash(尽管它们有不同的类型,比如1和1.0)。 
185 dic = {'dsaasd;sadasqwdzcs;121saddfsssxa': 1} 
186 i = hash('dsaasd;sadasqwdzcs;121saddfsssxa') 
187 print(i) #输出:9127798505667503991 
188 
189 # isinstance(对象,类) 判断对象是否是某个类创建的 父类的话也成立 
190 li = [11, 22] 
191 r = isinstance(li, list) 
192 r1 = isinstance(li, dict) 
193 print(r, r1) # 输出True False 
194 
195 
196 # iter 迭代器 
197 obj = iter([1, 2, 3, 4])
198 print(obj) 
199 next(obj) # 执行next方法 
200 r = next(obj) 
201 print(r) 
202 # 输出: 
203 # <list_iterator object at 0x000000000118E400> 
204 # 2 
205 
206 # max,min 最大值,最小值 
207 l1 = [1, 22, -1, 0, 5] 
208 l2 = (111, 22, -11111, 0, 5) 
209 print(max(l1)) 
210 print(min(l2)) 
211 
212 # pow求次方 
213 i = pow(2, 10) 
214 print(i) 223 224 225 
215 
216 # round 四舍五入 
217 print "round(80.23456, 2) : ", round(80.23456, 2) 
218 print "round(100.000056, 3) : ", round(100.000056, 3) 
219 print "round(-100.000056, 3) : ", round(-100.000056, 3) 
220 round(80.23456, 2) : 80.23 230 round(100.000056, 3) : 100.0 
221 round(-100.000056, 3) : -100.0 232 233 print(round(80.23456, 2)) 
222 # 输出80.23 
223 
224 print(round(4.56, 1)) 
225 # 输出4.6 
226 
227 
228 # sum(iterable[, start]) 将start以及iterable的元素从左向右相加并返回总和。start默认为0。iterable的元素通常是数字,start值不允许是一个字符串。
229 r = sum(range(101)) # 计算1-100的和 
230 print(r) 240 a = range(1,11) 
231 b = range(1,10) 
232 c = sum([item for item in a if item in b]) # 列表解析,再用sum求和 
233 print(c) 244 245 246 # zip 拉链 将两个列表合起来,做成一个列表,元素为数组 
234 >>> b 248 [1, 2, 3, 4] 249 >>> a 
235 [5, 6, 7, 8, 9] 
236 >>> zip(a,b) 
237 [(5, 1), (6, 2), (7, 3), (8, 4)] 
238 
239 
240 
241 # sort 函数, 数字和字母不支持一起排序,可以把数字用引号变为字符串,再排序 
242 l = ['1', '22', '33', '-1', '-66', '4', 'a'] 257 l.sort() 258 print(l)

 max函数用法补充:

 1 # 可以通过传入命名参数key,指定取最大值方法。
 2 max(-1,0,key = abs) # 传入了求绝对值函数,则参数都会进行求绝对值后再取较大者
 3 -1
 4 
 5 # key参数的另外一个作用是,不同类型对象本来不能比较取最大值的,传入适当的key函数,变得可以比较能取最大值了。
 6 max(1,2,'3',key = int) # 指定key为转换函数后,可以取最大值
 7 '3'
 8 max((1,2),[1,1],key = lambda x : x[1]) #指定key为返回序列索引1位置的元素后,可以取最大值        # x就是(1,2),[1,1]两个元组的传参
 9 (1, 2)
10 
11 salaries = {
12     'egon': 3000,
13     'alex': 100000000,
14     'wupeiqi': 10000,
15     'yuanhao': 2000
16 }
17 a = max(salaries, key=lambda k: salaries[k])
18 print(a)              # alex
1 lambda x,req:self.inprogress.remove(req)
2 
3 执行lambda函数,形参:x,req;返回self.inprogress.remove(req)

 __dict__与dir()区别:

  1 Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案。
  2 
  3 __dict__与dir()的区别:
  4 
  5 dir()是一个函数,返回的是list;
  6 __dict__是一个字典,键为属性名,值为属性值;
  7 dir()用来寻找一个对象的所有属性,包括__dict__中的属性,__dict__是dir()的子集;
  8 ​ 并不是所有对象都拥有__dict__属性。许多内建类型就没有__dict__属性,如list,此时就需要用dir()来列出对象的所有属性。
  9 
 10 # __dict__属性:
 11 # __dict__是用来存储对象属性的一个字典,其键为属性名,值为属性的值。
 12 
 13 
 14 #!/usr/bin/python
 15 # -*- coding: utf-8 -*-
 16 class A(object):
 17     class_var = 1
 18     def __init__(self):
 19         self.name = 'xy'
 20         self.age = 2
 21 
 22     @property
 23     def num(self):
 24         return self.age + 10
 25 
 26     def fun(self):pass
 27     def static_f():pass
 28     def class_f(cls):pass
 29 
 30 if __name__ == '__main__':#主程序
 31     a = A()
 32     print a.__dict__   #{'age': 2, 'name': 'xy'}   实例中的__dict__属性
 33     print A.__dict__   
 34     '''
 35     类A的__dict__属性
 36     {
 37     '__dict__': <attribute '__dict__' of 'A' objects>, #这里如果想深究的话查看参考链接5
 38     '__module__': '__main__',               #所处模块
 39     'num': <property object>,               #特性对象 
 40     'class_f': <function class_f>,          #类方法
 41     'static_f': <function static_f>,        #静态方法
 42     'class_var': 1, 'fun': <function fun >, #类变量
 43     '__weakref__': <attribute '__weakref__' of 'A' objects>, 
 44     '__doc__': None,                        #class说明字符串
 45     '__init__': <function __init__ at 0x0000000003451AC8>}
 46     '''
 47 
 48     a.level1 = 3
 49     a.fun = lambda :x
 50     print a.__dict__  #{'level1': 3, 'age': 2, 'name': 'xy','fun': <function <lambda> at 0x>}
 51     print A.__dict__  #与上述结果相同
 52 
 53     A.level2 = 4
 54     print a.__dict__  #{'level1': 3, 'age': 2, 'name': 'xy'}
 55     print A.__dict__  #增加了level2属性
 56 
 57     print object.__dict__
 58     '''
 59     {'__setattr__': <slot wrapper '__setattr__' of 'object' objects>, 
 60     '__reduce_ex__': <method '__reduce_ex__' of 'object' objects>, 
 61     '__new__': <built-in method __new__ of type object at>, 
 62     等.....
 63     '''
 64 
 65 # 从上述代码可知,
 66 
 67 实例的__dict__仅存储与该实例相关的实例属性,
 68 
 69 正是因为实例的__dict__属性,每个实例的实例属性才会互不影响。
 70 
 71 类的__dict__存储所有实例共享的变量和函数(类属性,方法等),类的__dict__并不包含其父类的属性。
 72 
 73 
 74 
 75 
 76 
 77 # dir()函数
 78# dir()是Python提供的一个API函数,dir()函数会自动寻找一个对象的所有属性(包括从父类中继承的属性)。
 79 
 80 ​ 一个实例的__dict__属性仅仅是那个实例的实例属性的集合,并不包含该实例的所有有效属性。所以如果想获取一个对象所有有效属性,应使用dir()。
 81 
 82 
 83 print dir(A)
 84 '''
 85 ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'class_f', 'class_var', 'fun', 'level1', 'level2', 'name', 'num', 'static_f']
 86 '''
 87 a_dict = a.__dict__.keys()
 88 A_dict = A.__dict__.keys()
 89 object_dict = object.__dict__.keys()
 90 print a_dict  
 91 print A_dict  
 92 print object_dict 
 93 '''
 94 ['fun', 'level1', 'age', 'name']
 95 
 96 ['__module__', 'level2', 'num', 'static_f', '__dict__', '__weakref__', '__init__', 'class_f', 'class_var', 'fun', '__doc__']
 97 
 98 ['__setattr__', '__reduce_ex__', '__new__', '__reduce__', '__str__', '__format__', '__getattribute__', '__class__', '__delattr__', '__subclasshook__', '__repr__', '__hash__', '__sizeof__', '__doc__', '__init__']
 99 '''
100 
101 #因为每个类都有一个__doc__属性,所以需要去重,去重后然后比较
102 print set(dir(a)) == set(a_dict + A_dict + object_dict)  #True
103 
104 
105 # 结论
106 dir()函数会自动寻找一个对象的所有属性,包括__dict__中的属性。
107 
108 __dict__是dir()的子集,dir()包含__dict__中的属性。
我们都知道Python一切皆对象,那么Python究竟是怎么管理对象的呢?
1、无处不在的__dict__
  首先看一下类的__dict__属性和类对象的__dict__属性

# -*- coding: utf-8 -*-


class A(object):
    """
    Class A.
    """

    a = 0
    b = 1

    def __init__(self):
        self.a = 2
        self.b = 3

    def test(self):
        print 'a normal func.'

    @staticmethod
    def static_test(self):
        print 'a static func.'

    @classmethod
    def class_test(self):
        print 'a calss func.'


obj = A()
print A.__dict__
print obj.__dict__

运行结果如下:

{'a': 0, '__module__': '__main__', 'b': 1, 'class_test': <classmethod object at 0x00000000021882E8>, '__dict__': <attribute '__dict__' of 'A' objects>, '__init__': <function __init__ at 0x00000000023A5BA8>, 'test': <function test at 0x00000000023A5C18>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': '
    Class A.
    ', 'static_test': <staticmethod object at 0x00000000021881C8>}
{'a': 2, 'b': 3}

由此可见, 类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类__dict__里的

对象的__dict__中存储了一些self.xxx的一些东西




2、Python里什么没有__dict__属性
  虽然说一切皆对象,但对象也有不同,就好比不是每个人的女朋友都是一个人一样,一些内置的数据类型是没有__dict__属性的,如下:

num = 3
ll = []
dd = {}
print num.__dict__
print ll.__dict__
print dd.__dict__



# 当我们运行这样的代码时,解释器就会告诉我们

Traceback (most recent call last):
  File "f:python	est.py", line 54, in <module>
    print num.__dict__
AttributeError: 'int' object has no attribute '__dict__'

Traceback (most recent call last):
  File "f:python	est.py", line 55, in <module>
    print ll.__dict__
AttributeError: 'list' object has no attribute '__dict__'

Traceback (most recent call last):
  File "f:python	est.py", line 56, in <module>
    print dd.__dict__
AttributeError: 'dict' object has no attribute '__dict__'

int, list, dict等这些常用的数据类型是没有__dict__属性的,其实这是可预料的,就算给了它们dict属性也没啥用,毕竟它们只是用来做数据容器的。


3、发生继承时候的__dict__属性
  子类有自己的__dict__, 父类也有自己的__dict__,子类的全局变量和函数放在子类的dict中,父类的放在父类dict中。


# -*- coding: utf-8 -*-


class Parent(object):
    a = 0
    b = 1

    def __init__(self):
        self.a = 2
        self.b = 3

    def p_test(self):
        pass


class Child(Parent):
    a = 4
    b = 5

    def __init__(self):
        super(Child, self).__init__()
        # self.a = 6
        # self.b = 7

    def c_test(self):
        pass

    def p_test(self):
        pass


p = Parent()
c = Child()
print Parent.__dict__
print Child.__dict__
print p.__dict__
print c.__dict__

# 运行上面的代码,结果入下:

{'a': 0, '__module__': '__main__', 'b': 1, '__dict__': <attribute '__dict__' of 'Parent' objects>, 'p_test': <function p_test at 0x0000000002325BA8>, '__weakref__': <attribute '__weakref__' of 'Parent' objects>, '__doc__': None, '__init__': <function __init__ at 0x0000000002325B38>}
{'a': 4, 'c_test': <function c_test at 0x0000000002325C88>, '__module__': '__main__', 'b': 5, 'p_test': <function p_test at 0x0000000002325CF8>, '__doc__': None, '__init__': <function __init__ at 0x0000000002325C18>}
{'a': 2, 'b': 3}
{'a': 2, 'b': 3}


  1)上段输出结果中,用红色字体标出的是类变量和函数,由结果可知,每个类的类变量、函数名都放在自己的__dict__中

  2) 再来看一下实力变量的__dict__中,由蓝色字体标识,父类和子类对象的__dict__是公用的

总结:

  1) 内置的数据类型没有__dict__属性

  2) 每个类有自己的__dict__属性,就算存着继承关系,父类的__dict__ 并不会影响子类的__dict__

  3) 对象也有自己的__dict__属性, 存储self.xxx 信息,父子类对象公用__dict__

 __setattr__:

# __setattr__ 每次给对象的属性设置值之前,会调用这个函数(每个设置值的方式都会进入这个方法)。
class A(object):

    def __init__(self, value, n):
        print("into __init__")
        self.value = value
        print("set n")
        self.n = n
        print("leave __init__")

    def __setattr__(self, name, value):
        print("into __setattr__")
        print("name:", name)
        print("value:", value)
        if value == 10:
            print("from __init__")
        # self.name = value         # 这样会导致死循环
        object.__setattr__(self, name, value)

a = A(10,100)
print(a.__dict__)
# 输出
# into __init__
# into __setattr__
# name: value
# value: 10
# from __init__
# set n
# into __setattr__
# name: n
# value: 100
# leave __init__
# {'value': 10, 'n': 100}

class _const(object):
    def __setattr__(self, name, value):
        if name in self.__dict__:
            raise ValueError("Can't rebind const (%s)" % name)
        if not name.isupper():
            raise ValueError("Const must be upper.")
        self.__dict__[name] = value
        print(self.__dict__)


const = _const()

const.DB_CONFIG_ITEM = 'databases'
const.NW_SALT = 'nw'
const.ALY_SALT = 'aly'


# 输出:
# {'DB_CONFIG_ITEM': 'databases'}
# {'NW_SALT': 'nw', 'DB_CONFIG_ITEM': 'databases'}
# {'ALY_SALT': 'aly', 'NW_SALT': 'nw', 'DB_CONFIG_ITEM': 'databases'}

 __getattr__:

# __getattr__:
# 当访问一个不存在的属性的时候,会抛出异常,提示我们不存在这个属性。
# 而这个异常就是__getattr__方法抛出的,其原因在于他是访问一个不存在的属性的最后落脚点,作为异常抛出的地方提示出错再适合不过了。
class A(object):
    def __init__(self, value):
        self.value = value

    def __getattr__(self, item):
        print(item)
        print("into __getattr__")
        return "can not find"


a = A(10)
print(a.value)

https://www.cnblogs.com/xybaby/p/6280313.html

三元运算:

1 flag = True
2 name = "whisky" if flag else "2333"
3 print(name)          # whisky

生成器:

 1 # 生成器,普通函数中如果使用了yield则表示这个函数变为生成器函数
 2 
 3 def xrange():
 4     print(11)
 5     yield 1             # yield后面的值返回给__next__方法接收
 6 
 7     print(22)
 8     yield 2
 9 
10     print(33)
11     yield 3
12 
13     print(44)
14     yield 4
15 
16     print(55)
17     yield 5
18 
19 r = xrange()    # 执行这个函数创建一个生成器
20 ret = r.__next__()      # 执行函数寻找下一个yeild
21 print(ret)
22 ret = r.__next__()
23 print(ret)
24 ret = r.__next__()
25 print(ret)
 1 #单步调试可以看到执行顺序
 2 def xrange():
 3     print('start')
 4     start = 0
 5     while True:
 6         yield start
 7         start += 1
 8 
 9 obj = xrange()
10 r = obj.__next__()
11 r = obj.__next__()
12 r = obj.__next__()
13 print(r)
14 
15 #输出
16 start
17 2
 1 #生成器, yield,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。保存上一次执行位置
 2 
 3 
 4 def xrange(n):
 5     start = 0
 6     while True:
 7         if start > n:
 8             return
 9         yield start
10         start += 1
11 
12 obj = xrange(15)
13 for i in obj:           # 直接使用for循环来迭代
14     print(i)

 补充:

 1 def xrange():
 2     start = 0
 3     while True:
 4         yield start
 5         start += 1
 6 
 7 obj = xrange()
 8 for i in obj:           # 直接使用for循环来迭代
 9     if i > 10:
10         break
11     print(i)
12 
13 
14 # 等价于 a = (x for x in range(4))
15 def gen():
16     for l in range(4):
17         yield l
18 a = gen()
19 
20 for i in a:
21     print(i)

 生成器表达式和列表解析

  1 迭代器协议
  2 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)
  3 
  4 2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)
  5 
  6 3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。
  7 
  8 
  9 
 10 for循环的本质:循环所有对象,全都是使用迭代器协议。
 11 
 12 正本清源:
 13 
 14 很多人会想,for循环的本质就是遵循迭代器协议去访问对象,那么for循环的对象肯定都是迭代器了啊,没错,那既然这样,for循环可以遍历(字符串,列表,元组,字典,集合,文件对象),那这些类型的数据肯定都是可迭代对象啊?但是,我他妈的为什么定义一个列表l=[1,2,3,4]没有l.next()方法,打脸么。
 15 
 16  
 17 
 18 (字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,调用了他们内部的__iter__方法,把他们变成了可迭代对象
 19 
 20 然后for循环调用可迭代对象的__next__方法去取值,而且for循环会捕捉StopIteration异常,以终止迭代
 21 
 22 for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,即在遍历之前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了
 23 
 24 l=['a','b','c']
 25 #一:下标访问方式
 26 print(l[0])
 27 print(l[1])
 28 print(l[2])
 29 # print(l[3])#超出边界报错:IndexError
 30 
 31 #二:遵循迭代器协议访问方式
 32 diedai_l=l.__iter__()
 33 print(diedai_l.__next__())
 34 print(diedai_l.__next__())
 35 print(diedai_l.__next__())
 36 # print(diedai_l.__next__())#超出边界报错:StopIteration
 37 
 38 #三:for循环访问方式
 39 #for循环l本质就是遵循迭代器协议的访问方式,先调用diedai_l=l.__iter__()方法,或者直接diedai_l=iter(l),然后依次执行diedai_l.next(),直到for循环捕捉到StopIteration终止循环
 40   #for循环所有对象的本质都是一样的原理
 41 
 42 for i in l:#diedai_l=l.__iter__()
 43     print(i) #i=diedai_l.next()
 44 
 45 #四:用while去模拟for循环做的事情
 46 diedai_l=l.__iter__()
 47 while True:
 48     try:
 49         print(diedai_l.__next__())
 50     except StopIteration:
 51         print('迭代完毕了,循环终止了')
 52         break
 53         
 54         
 55         
 56         
 57 什么是生成器?
 58 可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象
 59 
 60 生成器分类及在python中的表现形式:(Python有两种不同的方式提供生成器)
 61 
 62 1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
 63 
 64 2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
 65 
 66  
 67 
 68 为何使用生成器之生成器的优点
 69 
 70 Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。
 71 
 72  
 73 
 74 生成器小结:
 75 
 76 1.是可迭代对象
 77 
 78 2.实现了延迟计算,省内存
 79 
 80 3.生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算省内存的好处,其余的可迭代对象可没有这点好处
 81 
 82 
 83 
 84 
 85 # 生成器表达式和列表解析
 86 
 87 egg_list=['鸡蛋%s' %i for i in range(10)] #列表解析
 88 
 89 
 90 laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式
 91 print(laomuji)
 92 print(next(laomuji)) #next本质就是调用__next__
 93 print(laomuji.__next__())
 94 print(next(laomuji))
 95 
 96 
 97 总结:
 98 
 99 1.把列表解析的[]换成()得到的就是生成器表达式
100 
101 2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
102 
103 3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:
104 
105 sum(x ** 2 for x in xrange(4))
106 
107 而不用多此一举的先构造一个列表:sum([x ** 2 for x in xrange(4)]) 
108 
109 
110 
111 
112 
113 
114 八 生成器总结
115 综上已经对生成器有了一定的认识,下面我们以生成器函数为例进行总结
116 
117 语法上和函数类似:生成器函数和常规函数几乎是一样的。它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值
118 自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中(如for循环,sum函数)。由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且,在没有值可以返回的时候,生成器自动产生StopIteration异常
119 状态挂起:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行
120 
121 
122 
123 优点:生成器的好处是延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。
124 #列表解析
125 sum([i for i in range(100000000)])#内存占用大,机器容易卡死
126 
127 #生成器表达式
128 sum(i for i in range(100000000))#几乎不占内存
129 
130 
131 注意事项:生成器只能遍历一次
132 
133 人口信息.txt文件内容:
134 {'name':'北京','population':10}
135 {'name':'南京','population':100000}
136 {'name':'山东','population':10000}
137 {'name':'山西','population':19999}
138 def get_provice_population(filename):
139     with open(filename) as f:
140         for line in f:
141             p = eval(line)
142             yield p['population']
143 
144 
145 gen = get_provice_population('a')
146 
147 all_population = sum(gen)
148 # for p in gen:
149 #     print(p / all_population)
150 print(all_population)
151 
152 
153 
154 def test():
155     for i in range(4):
156         yield i
157 
158 
159 g = test()
160 
161 g1 = (i for i in g)
162 g2 = (i for i in g1)
163 g3 = (i for i in g)
164 
165 
166 print(list(g1))  # [0, 1, 2, 3]
167 print(list(g2))  # []  生成器只能生成一次,所以为空列表
168 print(list(g3))  # []  生成器只能生成一次,所以为空列表
169 
170 
171 
172 
173 
174 
175 
176 
177 对于生成一个列表:
178 
179 #循环方法(效率低):
180 goods_list = []
181 for i in range(10):
182     goods_list.append(i)
183 print(goods_list)
184 
185 
186 
187 # 列表解析方法:
188 goods_list = [i for i in range(10)]        # 列表解析中还可以加条件goods_list2 = [i for i in range(10) if i > 5] 
189 
190 
191 
192 # 三元运算
193 name = 'alex'
194 ret = 'SB' if name == 'alex' else 'blex'
195 print(ret)
196 
197 
198 
199 当goods_list非常大时列表解析方法耗内存严重
200 
201 
202 # 生成器表达式方法:
203 goods_list3 = (i for i in range(10))     # 生成器对象转列表:goods_list3 = list((i for i in range(10)))
204 
205 print(goods_list3)    # 返回一个生成器对象
迭代器,生成器
 1 def add(n, i):
 2     print('n:', n, 'i:', i, 'n+i:', n + i)
 3     return n + i
 4 
 5 
 6 def test():
 7     for i in range(4):
 8         yield i
 9 
10 
11 g = test()
12 print('g: ========', g)
13 for n in [1, 10]:       # 生成两个生成器迭代对象,第一个生成器迭代对象的结果赋值给第二个生成器中的i,n的值始终覆盖为10
14     print(n, 1)
15     g = (add(n, i) for i in g)
16     print(g)
17     print(n, 10)
18 
19 print('g: ========', g)
20 print(list(g))
练习
 1 '''
 2 闭包:在一个作用域里放入定义变量,相当于打了一个包
 3 '''
 4 def father(name):
 5     def son():
 6         # name='alex'
 7         print('我爸爸是 [%s]' %name)
 8         def grandson():
 9             # name='wupeiqi'
10             print('我爷爷是 [%s]' %name)
11         grandson()
12     son()
13 
14 father('whisky')

yield使用总结:

 1 def yield_test(n):
 2     for i in range(n):                        # 1
 3         yield call(i)                        # 2            # 执行call函数之后,返回值给外面的for循环,
 4         print("in yield_test -- i=", i)        # 5
 5     # 做一些其它的事情
 6     print("do something.")
 7     print("end.")
 8 
 9 
10 def call(i):                
11     return i * 2                            # 3
12 
13 
14 # 使用for循环
15 for i in yield_test(5):                        # 0        # 5
16     print(i, "in for---")                    # 4  
17 
18 # 理解的关键在于:下次迭代时,代码从yield的下一跳语句开始执行。
19 # 输出:
20 # 0 in for---
21 # in yield_test -- i= 0
22 # 2 in for---
23 # in yield_test -- i= 1
24 # 4 in for---
25 # in yield_test -- i= 2
26 # 6 in for---
27 # in yield_test -- i= 3
28 # 8 in for---
29 # in yield_test -- i= 4
30 # do something.
31 # end.
32 
33 小结yeild:
34 0.yeild用于函数中
35 1.执行了yield,就相当于返回一个生成器对象,可用于迭代
36 2.yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的;下一次迭代时,从上一次迭代遇到的yield后面的代码(下一行)开始执行
37 3. yield 可以返回变量,也可以返回函数

主要记住两点:

1.yield退出所在函数并返回一个生成器,可迭代对象;

2.迭代这个生成器时,继续从上次yield的位置向后执行

参考:

https://www.jianshu.com/p/d09778f4e055

列表推导式:

# 有一个嵌套列表,a=[[1,2],[3,4],[5,6]],要提取列表里的每一个元素

用for循环处理:

for i in a:
    for j in i:
        print(j)


b=[j for i in a for j in i] # 左侧是外层循环,右侧是内层for循环
 
print(b)
 
>>> b
[1, 2, 3, 4, 5, 6]

 https://blog.csdn.net/weixin_44695969/article/details/96889580

原文地址:https://www.cnblogs.com/yum777/p/7429253.html