1. 程式人生 > >Python 有哪些讓你相見恨晚的技巧?

Python 有哪些讓你相見恨晚的技巧?

關注「實驗樓」,每天分享一個專案教程

實驗樓高階工程師protream老師,為大家帶來這些Python黑魔法:有的能網頁速度提高3倍,有的可以把數十行程式碼濃縮成幾行,瞭解一下。

正文共:2889 字 

預計閱讀時間:8 分鐘

實驗樓python高階工程師@protream總結了一些他在工作中用到過,個人認為比較 Pythonic 的一些小技巧:

cached_property

它的作用是將一個方法的計算結果快取到物件的 __dict__當中,熟悉 Flask 的人對這個應該不陌生,Django 應該也有類似的實現。這是werkzeug中的原始碼實現:

class cached_property(property
):

def __init__(self, func, name=None, doc=None):
self.__name__ = name or func.__name__
self.__module__ = func.__module__
self.__doc__ = doc or func.__doc__
self.func = func

def __set__(self, obj, value):
obj.__dict__[self.__name__] = value

def __get__(self, obj, type=None):
if obj is None:
return self
value =
obj.__dict__.get(self.__name__, _missing)
if value is _missing:
value = self.func(obj)
obj.__dict__[self.__name__] = value
return value

曾經主要運用這個將公司網站的一個頁面效能提升了 3~4 倍。Flask 自己實現了一個執行緒安全的版本,locked_cached_property

class locked_cached_property(object):
def __init__(self, func, name=None, doc=None):
self.__name__
= name or func.__name__
self.__module__ = func.__module__
self.__doc__ = doc or func.__doc__
self.func = func
self.lock = RLock()

def __get__(self, obj, type=None):
if obj is None:
return self
with self.lock:
value = obj.__dict__.get(self.__name__, _missing)
if value is _missing:
value = self.func(obj)
obj.__dict__[self.__name__] = value
return value

類方法裝飾器

學習 Python 一段時間應該都知道裝飾器是什麼了,也應該知道怎麼寫一個簡單的裝飾器了。但是如果想裝飾一個類方法,怎麼去訪問到當前的物件或者類?在普通裝飾器中是不太好做到的,這時候就需要藉助描述器了。上面的 cached_property的實現就是一個示範。用cached_property裝飾一個類方法後,當該方法被以屬性的方式呼叫後,物件和類會被分別傳遞到objtype引數中。

基於這個特性可以實現一個和 @property對應的類屬性裝飾器@classpropertyclass

classproperty(object):

def __init__(self, func):
self.func = classmethod(func)

def __get__(self, obj=None, type=None):
return self.func.__get__(obj, type)()

使用它可以將一個 classmethod 以屬性的方式訪問。

Python 單列模式

在網上搜索 Python 單例模式,能找到很多中實現,比如這樣的:

class Singleton(object):

def __init__(self):
pass

@classmethod
def instance(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
Singleton._instance = Singleton(*args, **kwargs)
return Singleton._instance

或者這樣的:

def Singleton(cls):
_instance = {}

def _singleton(*args, **kargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kargs)
return _instance[cls]

return _singleton


@Singleton
class A(object):
a = 1

def __init__(self, x=0):
self.x = x

私以為如果真正理解 Python 的話,下面的才是 Pythonic 的做法:

class Singleton(object):
def foo(self):
pass
singleton = Singleton()

將上面的程式碼在 a.py 中,那麼在中用的地方匯入的 singleton就是單例的。

from a import singleton

將一個物件轉化成字典

如果一個類定義了 __getitem__keys那麼它的物件就能用 dict 函式轉化成字典:

>>> class Person:
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def __getitem__(self, key):
... return getattr(self, key)
... def keys(self):
... return ('name', 'age')
...

>>> p = Person('Jike', 20)
>>> dict(p)
{'age': 20, 'name': 'Jike'}

這個特性有什麼用處呢?舉個例子,在些 Flask WEB 應用時,介面需要返回 jSON 序列化的分頁資料,我們可以改造 flask-sqlalchemyPagination物件:

from flask_sqlalchemy import Pagination as _Pagination

class Pagination(_Pagination):
def __getitem__(self, key):
return getattr(self, key)

def items(self):
def keys(self):
return (
'page', 'pages', 'total', 'items',
'has_prev', 'next_num', 'has_next'
)

這樣分頁物件就能很方便的轉換成字典了。

作者:實驗樓工程師 鄭楠GitHub: protream (Zheng Nan)Python學習:Python_精選專案課程

640?

640?wx_fmt=1