重点汇总-python-gitbook-重要点学习-1

2017-12-19  本文已影响110人  时间之友

Python中关键字yield有什么作用?

为了理解yield有什么用,首先得理解generators,而理解generators前还要理解iterables

Iterables
当你创建了一个列表,你可以一个一个的读取它的每一项,这叫做iteration:

>>> mylist = [1, 2, 3]
>>> for i in mylist:
...    print(i)
1
2
3

Mylist是可迭代的.当你用列表推导式的时候,你就创建了一个列表,而这个列表也是可迭代的:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
...    print(i)
0
1
4

所有你可以用在for...in...语句中的都是可迭代的:比如lists,strings,files...因为这些可迭代的对象你可以随意的读取所以非常方便易用,但是你必须把它们的值放到内存里,当它们有很多值时就会消耗太多的内存.

Generators
生成器也是迭代器的一种,但是你只能迭代它们一次.原因很简单,因为它们不是全部存在内存里,它们只在要调用的时候在内存里生成:

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...    print(i)
0
1
4

生成器和迭代器的区别就是用()代替[],还有你不能用for i in mygenerator第二次调用生成器:首先计算0,然后会在内存里丢掉0去计算1,直到计算完4.
-----注:若二次调用即出现闭包现象,很容易出错,廖在闭包处多次强调

再谈 yield & return 点击参考我之前文章


Python中的元类(metaclass)是什么?

metaclass,直译为元类,简单的解释就是:
当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。

元类负责创建类, 类负责创建实例,主要应用在ORM上


用Python如何一个文件是否存在?

不用try:语句可以一个文件存在
如果不确定文件存不存在,可以这样做:

import os.path
os.path.isfile(fname)   # ⚠️举例 os.path.isfile('  /Users/jkx/Desktop/hello.txt  ')    ' ' 号不可少,否则报错。结果会提示 True or False

在Python中有三元运算符吗?

语法如下:

a if test else b     # 牢记!

来个大栗子:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

在Python中调用外部命令? (不太懂)

 print subprocess.Popen("echo Hello World",     shell=True,stdout=PIPE).stdout.read()

而用os.popen:

 print os.popen("echo Hello World").read()

它最大的优点就是一个类里代替了原来的4个不同的popen

 return_code = subprocess.call("echo Hello World", shell=True)

在Python里如何用枚举类型?

from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

这样我们就获得了Month类型的枚举类,可以直接使用Month.Jan来引用一个常量,或者枚举它的所有成员:

for name, member in Month.__members__.items():
    print(name, '=>', member, ',', member.value)

value属性则是自动赋给成员的int常量,默认从1开始计数。

如果需要更精确地控制枚举类型,可以从Enum派生出自定义类:

from enum import Enum, unique

@unique
class Weekday(Enum):
    Sun = 0 # Sun的value被设定为0
    Mon = 1
    Tue = 2
    Wed = 3
    ... ...

参考我之前文章


如何在一个表达式里合并两个字典?

我有两个Python字典,我想写一个表达式来返回两个字典的合并.update()方法返回的是空值而不是返回合并后的对象.

>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = x.update(y)
>>> print z
None
>>> x
{'a': 1, 'b': 10, 'c': 11}

怎么样才能最终让值保存在z而不是x?

>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}     # 字典中key必须唯一的,这里 'b' 用的是y的值

或者:

z = x.copy()     # 涉及 copy()  update() 用法
z.update(y)

装饰器@staticmethod和@classmethod有什么区别?

参考知乎

class A(object):  
    # 实例方法  
   def foo(self,x):  
        print "executing foo(%s,%s)"%(self,x)  
    # 类方法  
    @classmethod  
    def class_foo(cls,x):  
        print "executing class_foo(%s,%s)"%(cls,x)  
    # 静态方法  
    @staticmethod  
    def static_foo(x):  
        print "executing static_foo(%s)"%x  
  
a = A()    # 结果下图

可以看到,实例是三种方法都可以调用的,而类只可以调用两种。所以这些方法的使用就是看你是否要让类不需要通过实例来调用方法,而类方法和静态方法的区别就是你是否要在该方法引导类的属性或者其他类的类方法

知乎的解释:

一个基本的实例方法就向下面这个:
class Kls(object):
    def __init__(self, data):
        self.data = data
    def printd(self):
        print(self.data)
ik1 = Kls('arun')
ik2 = Kls('seema')
ik1.printd()     #  arun
ik2.printd()     #  seema

然后看一下代码和示例图片:

如果现在我们想写一些仅仅与类交互而不是和实例交互的方法会怎么样呢? 我们可以在类外面写一个简单的方法来做这些,但是这样做就扩散了类代码的关系到类定义的外面. 如果像下面这样写就会导致以后代码维护的困难:

def get_no_of_instances(cls_obj):
    return cls_obj.no_inst
class Kls(object):
    no_inst = 0
    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1
ik1 = Kls()
ik2 = Kls()
print(get_no_of_instances(Kls))     # 输出 2

@classmethod
我们要写一个只在类中运行而不在实例中运行的方法. 如果我们想让方法不在实例中运行,可以这么做:

def iget_no_of_instance(ins_obj):
    return ins_obj.__class__.no_inst
class Kls(object):
    no_inst = 0
    def __init__(self):
    Kls.no_inst = Kls.no_inst + 1
ik1 = Kls()
ik2 = Kls()
print iget_no_of_instance(ik1)     #  输出 2

在Python2.2以后可以使用@classmethod装饰器来创建类方法:

class Kls(object):
    no_inst = 0
    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1
    @classmethod
    def get_no_of_instance(cls_obj):
        return cls_obj.no_inst
ik1 = Kls()
ik2 = Kls()
print ik1.get_no_of_instance()    # 2
print Kls.get_no_of_instance()    # 2

这样的好处是: 不管这个方式是从实例调用还是从类调用,它都用第一个参数把类传递过来.

@staticmethod
经常有一些跟类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法. 比如更改环境变量或者修改其他类的属性等能用到静态方法. 这种情况可以直接用函数解决, 但这样同样会扩散类内部的代码,造成维护困难.
比如这样:

IND = 'ON'
def checkind():
    return (IND == 'ON')
class Kls(object):
     def __init__(self,data):
        self.data = data
def do_reset(self):
    if checkind():
        print('Reset done for:', self.data)
def set_db(self):
    if checkind():
        self.db = 'new db connection'
        print('DB connection made for:',self.data)
ik1 = Kls(12)
ik1.do_reset()      #  Reset done for: 12
ik1.set_db()        #  DB connection made for: 12

如果使用@staticmethod就能把相关的代码放到对应的位置了.

IND = 'ON'
class Kls(object):
    def __init__(self, data):
        self.data = data
    @staticmethod
    def checkind():
        return (IND == 'ON')
    def do_reset(self):
        if self.checkind():
            print('Reset done for:', self.data)
    def set_db(self):
        if self.checkind():
            self.db = 'New db connection'
        print('DB connection made for: ', self.data)
ik1 = Kls(12)
ik1.do_reset()   #  Reset done for: 12
ik1.set_db()     #  DB connection made for: 12

下面这个更全面的代码和图示来展示这两种方法的不同
@staticmethod@classmethod的不同

class Kls(object):
    def __init__(self, data):
        self.data = data
    def printd(self):
        print(self.data)
    @staticmethod
    def smethod(*arg):
        print('Static:', arg)
    @classmethod
    def cmethod(*arg):
        print('Class:', arg)
 
>>> ik = Kls(23)
>>> ik.printd()
23
>>> ik.smethod()
Static: ()
>>> ik.cmethod()
Class: (<class '__main__.Kls'>,)
>>> Kls.printd()
TypeError: unbound method printd() must be called with Kls instance as first argument (got nothing instead)
>>> Kls.smethod()
Static: ()
>>> Kls.cmethod()
Class: (<class '__main__.Kls'>,)

下面这个图解释了以上代码是怎么运行的:


上一篇 下一篇

猜你喜欢

热点阅读