python
1.析构问题:
python
import gc
#del之后 调用gc.collect()
#当有数据写入硬盘的时候,一定要显式清空变量内的数据
templist = templist[:]
del templist
gc.collect()
2.2b 语法
class UpperAttrMetaClass(type):
def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr):
attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
return type(future_class_name, future_class_parents, uppercase_attr)
####
a = [1,2,3,4,5,6]
b = (value for value in a if value < 5)
print type(b) --------------->is a generator
for i in b:
print i
怎样创建一个python generator?
就像创建一个函数一样简单,只不过不使用return 声明,而是使用yield声明.
如果一个函数至少包含一个yield声明(当然它也可以包含其他yield或return),那么它就是一个generator.
yield和return都会让函数返回一些东西,区别在于,return声明彻底结束一个函数,而yield声明是暂停函数,保存它的所有状态,并且后续被调用后会继续执行.
generator函数和普通函数的区别
- generator函数包含一个以上的yield声明
- generator函数被调用的时候,会返回一个iterator对象,但是函数并不会立即开始执行
- __iter__()和__next__()方法被自动实现,所以可以使用next()函数对返回的此iterator对象进行迭代
- 一旦一个generator 执行到yield语句,generator函数暂停,程序控制流被转移到调用方
- 在对generator的连续调用之间,generator的本地变量和状态会被保存
- 最终,generator函数终止,再调用generator会引发StopIteration异
- 下面这个例子说明上述全部要点,我们有一个名为my_gen()的函数,它带有一些yield声明.
# A simple generator function def my_gen(): n = 1 print('This is printed first') # Generator function contains yield statements yield n n += 1 print('This is printed second') yield n n += 1 print('This is printed at last') yield n a = my_gen() a.next() a.next() b = my_gen() b.next() This is printed first This is printed second This is printed first
通常来说,generator都是和循环结合实现的,且这个循环带有一个终止条件。 我们来看一个reverse一个字符串的例子 def rev_str(my_str): length = len(my_str) for i in range(length - 1,-1,-1): yield my_str[i] # For loop to reverse the string # Output: # o # l # l # e # h for char in rev_str("hello"): print(char)
python generator 表达式
使用generator表达式可以很容易地创建简单的generator。
就像lambda函数可以创建匿名函数一样,generator函数创建一个匿名generator函数。
generator表达式的语法类似于python的list comprehension,只是方括号被替换为了圆括号而已。
list comprehension和generator表达式的主要区别在于,前者产生全部的list,后者每次仅产生一项。
它们有些懒惰,仅在接到请求的时候才会产生输出。因此,generator表达式比list comprehension更加节省内存。
# Initialize the list my_list = [1, 3, 6, 10] # square each term using list comprehension # Output: [1, 9, 36, 100] [x**2 for x in my_list] # same thing can be done using generator expression # Output: <generator object <genexpr> at 0x0000000002EBDAF8> (x**2 for x in my_list) 上面的例子中,generator表达式没有立即产生需要的结果,而是在需要产生item的时候返回一个generator对象。 # Intialize the list my_list = [1, 3, 6, 10] a = (x**2 for x in my_list) # Output: 1 print(next(a)) # Output: 9 print(next(a)) # Output: 36 print(next(a)) # Output: 100 print(next(a)) # Output: StopIteration next(a)
generator表达式可以在函数内部使用。当这样使用的时候,圆括号可以丢弃。
python里为什么要使用generator?
1.容易实现
相对于iterator类来说,generator的实现清晰、简洁。下面是用iterator实现一个2的指数函数
class PowTwo: def __init__(self, max = 0): self.max = max def __iter__(self): self.n = 0 return self def __next__(self): if self.n > self.max: raise StopIteration result = 2 ** self.n self.n += 1 return result generator这样实现 def PowTwoGen(max = 0): n = 0 while n < max: yield 2 ** n n += 1
因为generator自动跟踪实现细节,因此更加清晰、简洁。
2.节省内存
一个函数返回一个序列(sequence)的时候,会在内存里面把这个序列构建好再返回。如果这个序列包含很多数据的话,就过犹不及了。
而如果序列是以generator方式实现的,就是内存友好的,因为他每次只产生一个item。
缺点:由于每次只生成一个item 那么之前的数据就会消失,除非你拷贝出来
super():
super() 函数用于调用下一个父类(超类)并返回该父类实例的方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
issubclass():
issubclass() 方法用于判断参数 class 是否是类型参数 classinfo 的子类。issubclass(class, classinfo);
*argparse module
是python的一个命令行解析包,可以用来指定参数。
直接输入的参数:
#pro.py import argparse parser = argparse.ArgumentParser() parser.add_argument( 'format', nargs='?', default='simple', help='the output format', ) python pro.py sss 输出: sss
输入指定的参数:
-v是短参数,--verbosity是长参数。
import argparse parser = argparse.ArgumentParser() parser.add_argument("-v", "--verbosity", help="increase output verbosity") args = parser.parse_args() if args.verbosity: print "verbosity turned on" >python prog.py -v 1 verbosity turned on >python prog.py --verbosity 1 verbosity turned on >python prog.py -h usage: prog.py [-h] [-v VERBOSITY] optional arguments: -h, --help show this help message and exit -v VERBOSITY, --verbosity VERBOSITY increase output verbosity >python prog.py -v usage: prog.py [-h] [-v VERBOSITY] prog.py: error: argument -v/--verbosity: expected one argument
action='store_true':
-v
没有指定任何参数也可,其实存的是True
和False
,如果出现,则其值为True
,否则为False.
#!/usr/bin/env python # encoding: utf-8 import argparse parser = argparse.ArgumentParser() parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true") args = parser.parse_args() if args.verbose: print "verbosity turned on"
类型 type:
#!/usr/bin/env python # encoding: utf-8 import argparse parser = argparse.ArgumentParser() parser.add_argument('x', type=int, help="the base") args = parser.parse_args() answer = args.x ** 2 print answer
可选值choices=[]:
#!/usr/bin/env python # encoding: utf-8 import argparse parser = argparse.ArgumentParser() parser.add_argument("square", type=int, help="display a square of a given number") parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2], help="increase output verbosity") args = parser.parse_args() answer = args.square**2 if args.verbosity == 2: print "the square of {} equals {}".format(args.square, answer) elif args.verbosity == 1: print "{}^2 == {}".format(args.square, answer) else: print answer
程序用法帮助:
parser = argparse.ArgumentParser(description="calculate X to the power of Y")
互斥参数:
group = parser.add_mutually_exclusive_group() group.add_argument("-v", "--verbose", action="store_true") group.add_argument("-q", "--quiet", action="store_true")
第一行定义了一个互斥组,第二、三行在互斥组中添加了-v
和-q
两个参数.可以看出,-q
和-v
不出现,或仅出现一个都可以,同时出现就会报错。可定义多个互斥组.
Python 模块导入:
在没有明确指定包结构的情况下,Python 是根据 __name__
来决定一个模块在包中的结构的,如果是 __main__
则它本身是顶层模块,没有包结构,如果是A.B.C
结构,那么顶层模块是 A。基本上遵循这样的原则:
- 如果是绝对导入,一个模块只能导入自身的子模块或和它的顶层模块同级别的模块及其子模块
- 如果是相对导入,一个模块必须有包结构且只能导入它的顶层模块内部的模块
如果一个模块被直接运行,则它自己为顶层模块,不存在层次结构,所以找不到其他的相对路径。
Python2.x 缺省为相对路径导入,Python3.x 缺省为绝对路径导入。绝对导入可以避免导入子包覆盖掉标准库模块(由于名字相同,发生冲突)。如果在 Python2.x 中要默认使用绝对导入,可以在文件开头加入如下语句:
from __future__ import absolute_import
from __future__ import absolute_import
这句 import 并不是指将所有的导入视为绝对导入,而是指禁用 implicit relative import
(隐式相对导入), 但并不会禁掉 explicit relative import
(显示相对导入)。
那么到底什么是隐式相对导入,什么又是显示的相对导入呢?我们来看一个例子,假设有如下包结构:
那么如果在 stool 中引用 bench,则有如下几种方式:
import bench # 此为 implicit relative import from . import bench # 此为 explicit relative import from furniture import bench # 此为 absolute import
隐式相对就是没有告诉解释器相对于谁,但默认相对与当前模块;而显示相对则明确告诉解释器相对于谁来导入。以上导入方式的第三种,才是官方推荐的,第一种是官方强烈不推荐的,Python3 中已经被废弃,这种方式只能用于导入 path 中的模块。
相对与绝对仅针对包内导入而言
最后再次强调,相对导入与绝对导入仅针对于包内导入而言,要不然本文所讨论的内容就没有意义。所谓的包,就是包含 __init__.py
文件的目录,该文件在包导入时会被首先执行,该文件可以为空,也可以在其中加入任意合法的 Python 代码。
相对导入可以避免硬编码,对于包的维护是友好的。绝对导入可以避免与标准库命名的冲突,实际上也不推荐自定义模块与标准库命令相同。
前面提到含有相对导入的模块不能被直接运行,实际上含有绝对导入的模块也不能被直接运行,会出现 ImportError.
##引用http://kuanghy.github.io/2016/07/21/python-import-relative-and-absolute
Pandas DataFrames 是个好工具
dict = {"country": ["Brazil", "Russia", "India", "China", "South Africa"], "capital": ["Brasilia", "Moscow", "New Dehli", "Beijing", "Pretoria"], "area": [8.516, 17.10, 3.286, 9.597, 1.221], "population": [200.4, 143.5, 1252, 1357, 52.98] } import pandas as pd brics = pd.DataFrame(dict) print(brics) area capital country population 0 8.516 Brasilia Brazil 200.40 1 17.100 Moscow Russia 143.50 2 3.286 New Dehli India 1252.00 3 9.597 Beijing China 1357.00 4 1.221 Pretoria South Africa 52.98
# Set the index for brics brics.index = ["BR", "RU", "IN", "CH", "SA"] # Print out brics with new index values print(brics) area capital country population BR 8.516 Brasilia Brazil 200.40 RU 17.100 Moscow Russia 143.50 IN 3.286 New Dehli India 1252.00 CH 9.597 Beijing China 1357.00 SA 1.221 Pretoria South Africa 52.98
# Import pandas as pd import pandas as pd # Import the cars.csv data: cars cars = pd.read_csv('cars.csv') # Print out cars print(cars) Unnamed: 0 cars_per_cap country drives_right 0 US 809 United States True 1 AUS 731 Australia False 2 JAP 588 Japan False 3 IN 18 India False 4 RU 200 Russia True 5 MOR 70 Morocco True 6 EG 45 Egypt True
# Import pandas and cars.csv import pandas as pd cars = pd.read_csv('cars.csv', index_col = 0) # Print out country column as Pandas Series print(cars['cars_per_cap']) # Print out country column as Pandas DataFrame print(cars[['cars_per_cap']]) # Print out DataFrame with country and drives_right columns print(cars[['cars_per_cap', 'country']]) US 809 AUS 731 JAP 588 IN 18 RU 200 MOR 70 EG 45 Name: cars_per_cap, dtype: int64 cars_per_cap US 809 AUS 731 JAP 588 IN 18 RU 200 MOR 70 EG 45 cars_per_cap country US 809 United States AUS 731 Australia JAP 588 Japan IN 18 India RU 200 Russia MOR 70 Morocco EG 45 Egypt
# Import cars data import pandas as pd cars = pd.read_csv('cars.csv', index_col = 0) # Print out first 4 observations print(cars[0:4]) # Print out fifth, sixth, and seventh observation print(cars[4:6]) cars_per_cap country drives_right US 809 United States True AUS 731 Australia False JAP 588 Japan False IN 18 India False cars_per_cap country drives_right RU 200 Russia True MOR 70 Morocco True
# Import cars data import pandas as pd cars = pd.read_csv('cars.csv', index_col = 0) # Print out observation for Japan print(cars.iloc[2]) # Print out observations for Australia and Egypt print(cars.loc[['AUS', 'EG']]) cars_per_cap 588 country Japan drives_right False Name: JAP, dtype: object cars_per_cap country drives_right AUS 731 Australia False EG 45 Egypt True
作者:yarving
链接:http://www.jianshu.com/p/fef2d215b91d
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。