Python 的奇淫技巧

3 min read

列了一些我新發現的各種花招

Function Attributes (python 2.1)

PEP 232

def a():
    a.count += 1

a.count = 0

for i in range(10):
    a()

print(a.count) # 10

跟 C++ 中,在 function 裡面宣告 static 變數差不多

Keyword-Only Arguments (python 3.0)

PEP 3102

def func(a, b, *, c = None):
    pass
  • func(1, 2, 3) 不行
  • func(1, 2, c = 3) 這樣才合法

Additional Unpacking Generalizations (python 3.5)

PEP 448

a = [1, 2, 3]
b = [*a, 4, 5]
print(b) # [1, 2, 3, 4, 5]

Merge Dicts

a = {1: 2}
b = {3: 4}
c = {**a, **b}
print(c) # {1: 2, 3: 4}

Metaclasses

Python Metaclasses

class A:
    pass

B = type('B',
         (A,),
         {
            'attr': 10,
            'func': lambda obj: obj.attr
         })

b = B()
print(b.attr)   # 10
print(b.func()) # 10
class A:
    pass

class B(A):
    attr = 10
    def func(self):
        return self.attr

b = B()
print(b.attr)   # 10
print(b.func()) # 10

看看就好 xD

shallow vs deep copy

Shallow vs Deep Copying of Python Objects

assign

a = [[1, 2, 3], [4, 5, 6]]
b = a

b.append('hello')
b[0].append('world')

print(a)
# [[1, 2, 3, 'world'], [4, 5, 6], 'hello']
print(b)
# [[1, 2, 3, 'world'], [4, 5, 6], 'hello']

copy

import copy

a = [[1, 2, 3], [4, 5, 6]]
b = copy.copy(a)

b.append('hello')
b[0].append('world')

print(a)
# [[1, 2, 3, 'world'], [4, 5, 6]]
print(b)
# [[1, 2, 3, 'world'], [4, 5, 6], 'new object']

deepcopy

import copy

a = [[1, 2, 3], [4, 5, 6]]
b = copy.deepcopy(a)

b.append('hello')
b[0].append('world')

print(a)
# [[1, 2, 3], [4, 5, 6]]
print(b)
# [[1, 2, 3, 'world'], [4, 5, 6], 'new object']
  • copy.copy (shallow) 只複製該物件,不會複製子物件
  • copy.deepcopy (deep) 會遞迴複製所有子物件

shallow copy on list

a = [1, 2, 3]
b = list(a)
a = [1, 2, 3]
b = a[:]
a = [1, 2, 3]
b = a.copy()
import copy

a = [1, 2, 3]
b = copy.copy(a)

annotations

function annotations

def func(a: int, b: list) -> int:
    pass

print(func.__annotations__)
# {'a': <class 'int'>, 'b': <class 'list'>, 'return': <class 'int'>}

class annotations

class A():
    var: int

print(A.__annotations__)
# {'var': <class 'int'>}

variable annotations

a: int
b: int = 2

print(__annotations__)
# {'a': <class 'int'>, 'b': <class 'int'>}

intern string

s = 'hello'
s = sys.intern(s)

把字串存進快取池,相同的字串只會存一次 做字串比對會比較快且節省空間


  1. http://guilload.com/python-string-interning/
  2. http://www.laurentluce.com/posts/python-string-objects-implementation/