Note for Taipei.py 2016/06/30 Meetup


Python 中常遇到的小錯誤 - Tim

Space vs Tab

若是縮排減少,會把堆疊 pop 到縮排與堆疊頂端一致。

Default Argument

def play(song_list=[]):  
    song_list.append('a random song')  
    print(song_list)  

play()  
play()  

=>

['a random song']  
['a random song', 'a random song']  

初始化只會初始一次

Closure

def outer():  
    outer_variable = 10  

    def common():  
        print(outer_variable)  

    outer_variable = 100  

    return common  

=>

outer()()  

100  
  • 當產生 Closure 的時候,Python 並沒有執行函數內的程式。
  • 裡面的變數還沒有取得 reference,Python 只是記住變數名字而已(Lexical Scope)
  • 被 closure 記住的變數,不會立刻被 GC。
def outer():  
    outer_variable = 10  

    def common(parameter=outer_variable):  
        print(parameter)  

    outer_variable = 100  

    return common  

=>

outer()()  

10  
  • 改成用 class, 並使用 __call__。資源抓取會更清楚,而不是依賴 lexical scope。
  • 或是使用 functool.partial

Global variable

value = 10  

def change():  
    value = 20  

change()  
print(value)  

=> 10  
value = 10  

def change():  
    value = value + 20  

change()  
print(value)  

=> UnboundError  
value = 10  

def change():  
    global value  
    value += 10  

change()  
print(value)  

=> 20  

del

class SimpleType(object):  
    def __init__(self):  
        print('simple born')  
    def __del__(self):  
        print('simple born')  

simple = SimpleType()  
del simple  
class FooType(object):  
    def __init__(self, parent):  
        self.parent = parent  
        print('Foo born')  

    def __del__(self):  
        print('Foo died')  

class BarType(object):  
    def __init__(self):  
        self = FooType(self)  
        print('Bar born')  

    def __del__(self):  
        print('Bar died')  

=>  
Foo born  
Bar born  
  • del 只會讓名字從 symbol table 消失,並讓 reference count - 1
  • 當 reference count 為 0 的時候,才會執行 GC 的動作(__del__)
  • 可以解決 Circular Reference 的問題
  • 有 circular reference 的時候 Python 不會真的執行 del

Interface

from abc import ABCMeta, abstractmethod  

class Sized:  
    __metaclass__ = ABCMeta  

    @abstractmethod  
    def __len__(self):  
        return 0  

class Missing(Sized):  
    pass  


Missing()  

=> TypeError  
    Can't instantiate abstract class Missing with abstract methods __len__  
class Struggle(object):  
    def __len__():  
        return 23  

isinstance(Struggle, Sized)  

=> True  

Duck Typing

List related

# Python 2  
data = range(10)  
for l in data:  
    data.remove(l)  
print(data)  
=> [1, 3, 5, 7, 9]  

# 跟 Python 的 list 實作採用 linked list 實作有關  
# Python 2  
data = range(10)  
for l in data[:]:  
    data.remove(l)  
print(data)  
=> []  

Package

  • 不要 pip freeze > requirements.txt
    • 會把 dependency 的 dependency 也寫進去,不知道到底真正要用的是哪些。

2 => 3

Quality

  • flake8
    • install-hook

Inheritance

  • 正確使用 super() 可以避免很多問題
class Base(object):  
    def __init__(self):  
        print("init Base")  

class Left(Base):  
    def __init__(self):  
        print("init Left")  

class Right(Base):  
    def __init__(self):  
        print("init Right")  

class C(Left, Right):  
    def __init__(self):  
        Left.__init__()  
        Right.__init__()  
        print("init C")  

=>  
init Base  
init Left  
init Base  
init Right  

Base.__init__() 有副作用的話就會很恐怖
正確的寫法要用 super()

Related links


Physics of IOT - David Mikolas


pynsist

  • py2exe
  • pip install pynsist

Lightning talks

  • PyCon TW 2017 主席開放報名中

Share


Donation

如果覺得這篇文章對你有幫助, 除了留言讓我知道外, 或許也可以考慮請我喝杯咖啡, 不論金額多寡我都會非常感激且能鼓勵我繼續寫出對你有幫助的文章。

If this blog post happens to be helpful to you, besides of leaving a reply, you may consider buy me a cup of coffee to support me. It would help me write more articles helpful to you in the future and I would really appreciate it.


Related Posts