Pythonプログラミング言語のあまり知られていないが便利な機能は何ですか?
.get
の値import this
__missing__
項目.pth
ファイルtry/except/else
print()
functionwith
ステートメントsum()
を使用して list
を平坦化します。sum()
組み込み関数を一緒に使用して __add__
list
sを作成することで、 list
of )を簡単にフラット化できます。 list
s:
Python 2.7.1 (r271:86832, May 27 2011, 21:41:45)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> l = [[1, 2, 3], [4, 5], [6], [7, 8, 9]]
>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
これは Alex Martelli からキラーです。 Borg
のすべてのインスタンスは状態を共有します。これにより、シングルトンパターンを使用する必要がなくなり(状態が共有される場合はインスタンスは関係ありません)、かなりエレガントになります(ただし、新しいクラスではより複雑になります)。
foo
の値はどのような場合でも再割り当てすることができ、すべて更新されます。辞書全体を再割り当てすることもできます。ボルグは完璧な名前です、続きを読みます ここ 。
class Borg:
__shared_state = {'foo': 'bar'}
def __init__(self):
self.__dict__ = self.__shared_state
# rest of your class here
これは、同時実行性を制御するためにeventlet.GreenPoolを共有するのに最適です。
トップシークレット属性
>>> class A(object): pass
>>> a = A()
>>> setattr(a, "can't touch this", 123)
>>> dir(a)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', "can't touch this"]
>>> a.can't touch this # duh
File "<stdin>", line 1
a.can't touch this
^
SyntaxError: EOL while scanning string literal
>>> getattr(a, "can't touch this")
123
>>> setattr(a, "__class__.__name__", ":O")
>>> a.__class__.__name__
'A'
>>> getattr(a, "__class__.__name__")
':O'
動的に追加された属性
あなたがそれらを呼び出すことによってあなたのクラスにいくつかの属性を追加することを考えるならば、これは役に立つかもしれません。これは、ドットオペランドを使用したときに呼び出される __getattribute__
メンバー関数をオーバーライドすることによって実行できます。それでは、たとえばダミークラスを見てみましょう。
class Dummy(object):
def __getattribute__(self, name):
f = lambda: 'Hello with %s'%name
return f
Dummyオブジェクトをインスタンス化してメソッドを呼び出すと、次のようになります。
>>> d = Dummy()
>>> d.b()
'Hello with b'
最後に、動的に定義できるように属性を自分のクラスに設定することもできます。これは、Python Webフレームワークを使用していて、属性の名前を解析してクエリを実行したい場合に便利です。
私は Gist にgithubで、この単純なコードとRuby上で同等のものを作りました。
世話をする!
>>> node = namedtuple('node', "a b")
>>> node(1,2) + node(5,6)
(1, 2, 5, 6)
>>> (node(1,2), node(5,6))
(node(a=1, b=2), node(a=5, b=6))
>>>
コメントに応答するためのいくつかの実験
>>> from collections import namedtuple
>>> from operator import *
>>> mytuple = namedtuple('A', "a b")
>>> yourtuple = namedtuple('Z', "x y")
>>> mytuple(1,2) + yourtuple(5,6)
(1, 2, 5, 6)
>>> q = [mytuple(1,2), yourtuple(5,6)]
>>> q
[A(a=1, b=2), Z(x=5, y=6)]
>>> reduce(operator.__add__, q)
(1, 2, 5, 6)
それで、namedtuple
は おもしろい Tuple
のサブタイプです。
関連データを持つ2つのシーケンスの辞書を作成する
In [15]: t1 = (1, 2, 3)
In [16]: t2 = (4, 5, 6)
In [17]: dict (Zip(t1,t2))
Out[17]: {1: 4, 2: 5, 3: 6}
threading.enumerate()はシステム内のすべてのThreadオブジェクトへのアクセスを許可し、sys._current_frames()はシステム内のすべてのスレッドの現在のスタックフレームを返すので、これら2つを組み合わせるとJavaスタイルのスタックダンプが得られます。
def dumpstacks(signal, frame):
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# Thread: %s(%d)" % (id2name[threadId], threadId))
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
if line:
code.append(" %s" % (line.strip()))
print "\n".join(code)
import signal
signal.signal(signal.SIGQUIT, dumpstacks)
マルチスレッドのpythonプログラムの始めにこれをしてください、そしてあなたはいつでもSIGQUITを送ることによってスレッドの現在の状態にアクセスすることができます。 signal.SIGUSR1またはsignal.SIGUSR2を選択することもできます。
pdb - Pythonデバッガ
プログラマとして、あなたが本格的なプログラム開発のためにあなたが最初に必要とするものの1つはデバッガです。 Pythonにはpdbと呼ばれるモジュールとして利用可能な組み込みのものがあります( "Python DeBugger"のために、当然!)。
inspect moduleも素晴らしい機能です。
モジュールをリロードすると、「ライブコーディング」スタイルが有効になります。しかし、クラスインスタンスは更新されません。その理由と回避方法は次のとおりです。覚えておいて、すべて、はい、 すべて はオブジェクトです。
>>> from a_package import a_module
>>> cls = a_module.SomeClass
>>> obj = cls()
>>> obj.method()
(old method output)
これで、a_module.pyのメソッドを変更して、オブジェクトを更新したいと思います。
>>> reload(a_module)
>>> a_module.SomeClass is cls
False # Because it just got freshly created by reload.
>>> obj.method()
(old method output)
これを更新する1つの方法があります(ただし、はさみで実行することを検討してください)。
>>> obj.__class__ is cls
True # it's the old class object
>>> obj.__class__ = a_module.SomeClass # pick up the new class
>>> obj.method()
(new method output)
オブジェクトの内部状態は、新しいクラスが期待するものとは異なる可能性があるため、これは「はさみで実行」されています。これは非常に単純な場合にも機能しますが、それを超えて、pickle
はあなたの友達です。それでも、なぜこれが機能するのかを理解することはまだ役に立ちます。
演算子は関数として呼び出すことができます。
from operator import add
print reduce(add, [1,2,3,4,5,6])
リスト内の無限再帰
>>> a = [1,2]
>>> a.append(a)
>>> a
[1, 2, [...]]
>>> a[2]
[1, 2, [...]]
>>> a[2][2][2][2][2][2][2][2][2] == a
True
dict.get()
は デフォルト値 Noneを持ち、それによってKeyErrorsを回避します。
In [1]: test = { 1 : 'a' }
In [2]: test[2]
---------------------------------------------------------------------------
<type 'exceptions.KeyError'> Traceback (most recent call last)
<ipython console> in <module>()
<type 'exceptions.KeyError'>: 2
In [3]: test.get( 2 )
In [4]: test.get( 1 )
Out[4]: 'a'
In [5]: test.get( 2 ) == None
Out[5]: True
そして「現場で」これを指定することすら:
In [6]: test.get( 2, 'Some' ) == 'Some'
Out[6]: True
そしてsetdefault(
)を使用して値を設定し、それが存在しない場合はそれを返すことができます。
>>> a = {}
>>> b = a.setdefault('foo', 'bar')
>>> a
{'foo': 'bar'}
>>> b
'bar
生の文字列内のバックスラッシュは引用符をエスケープすることができます。これを見なさい:
>>> print repr(r"aaa\"bbb")
'aaa\\"bbb'
最後の文字列にはバックスラッシュと二重引用符の両方があります。
結果として、生の文字列をバックスラッシュで終わらせることはできません。
>>> print repr(r"C:\")
SyntaxError: EOL while scanning string literal
>>> print repr(r"C:\"")
'C:\\"'
これは、生の文字列が正規表現の記述を助けるために実装されており、Windowsパスを記述するためではないために発生します。これについての長い議論は Gotcha - Windowsのファイル名のバックスラッシュで読んでください 。
小さい整数(-5 .. 256)のオブジェクトは二度作成されることはありません。
>>> a1 = -5; b1 = 256
>>> a2 = -5; b2 = 256
>>> id(a1) == id(a2), id(b1) == id(b2)
(True, True)
>>>
>>> c1 = -6; d1 = 257
>>> c2 = -6; d2 = 257
>>> id(c1) == id(c2), id(d1) == id(d2)
(False, False)
>>>
編集:リストオブジェクトが破壊されることはありません(リスト内のオブジェクトのみ)。 Pythonは最大80個の空リストを保持する配列を持っています。あなたがリストオブジェクトを破棄すると - pythonはそれをその配列に置き、あなたが新しいリストを作成すると - pythonはこの配列から最後に入力されたリストを取得します。
>>> a = [1,2,3]; a_id = id(a)
>>> b = [1,2,3]; b_id = id(b)
>>> del a; del b
>>> c = [1,2,3]; id(c) == b_id
True
>>> d = [1,2,3]; id(d) == a_id
True
>>>
左辺値としてのスライスこのエラトステネスのふるいは、素数または0のいずれかを持つリストを作成します。要素は、ループ内のスライスの割り当てで0になります。
def eras(n):
last = n + 1
sieve = [0,0] + list(range(2, last))
sqn = int(round(n ** 0.5))
it = (i for i in xrange(2, sqn + 1) if sieve[i])
for i in it:
sieve[i*i:last:i] = [0] * (n//i - i + 1)
return filter(None, sieve)
機能するには、左側のスライスに同じ長さの右側のリストを割り当てる必要があります。
丸め整数:Pythonには関数doubleがあり、double型の数を返します。
>>> print round(1123.456789, 4)
1123.4568
>>> print round(1123.456789, 2)
1123.46
>>> print round(1123.456789, 0)
1123.0
この関数は素晴らしい魔法の性質を持っています。
>>> print round(1123.456789, -1)
1120.0
>>> print round(1123.456789, -2)
1100.0
結果として整数が必要な場合は、intを使って型を変換します。
>>> print int(round(1123.456789, -2))
1100
>>> print int(round(8359980, -2))
8360000
ありがとうございます Gregor 。
再帰制限を操作する
Sys.getrecursionlimit()およびsys.setrecursionlimit()を使用して最大再帰深度を取得または設定します。
無限再帰によるスタックオーバーフローを防ぐために制限することができます。
メタクラスでクラスのmroを上書きすることができます
>>> class A(object):
... def a_method(self):
... print("A")
...
>>> class B(object):
... def b_method(self):
... print("B")
...
>>> class MROMagicMeta(type):
... def mro(cls):
... return (cls, B, object)
...
>>> class C(A, metaclass=MROMagicMeta):
... def c_method(self):
... print("C")
...
>>> cls = C()
>>> cls.c_method()
C
>>> cls.a_method()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'a_method'
>>> cls.b_method()
B
>>> type(cls).__bases__
(<class '__main__.A'>,)
>>> type(cls).__mro__
(<class '__main__.C'>, <class '__main__.B'>, <class 'object'>)
それはおそらく正当な理由で隠されています。 :)
ファイル削除、ファイルオープンなどのようなものでさえ代用する能力 - 言語ライブラリの直接操作 テストの場合、これは大きな利点です。 あなたはすべてを複雑なコンテナで包む必要はありません。関数/メソッドを置き換えるだけでいいのです。これは モンキーパッチとも呼ばれます。
スライスと可変性
リストをコピーする
>>> x = [1,2,3]
>>> y = x[:]
>>> y.pop()
3
>>> y
[1, 2]
>>> x
[1, 2, 3]
リストを置き換える
>>> x = [1,2,3]
>>> y = x
>>> y[:] = [4,5,6]
>>> x
[4, 5, 6]
入れ子関数パラメータの再結合
def create_printers(n):
for i in xrange(n):
def printer(i=i): # Doesn't work without the i=i
print i
yield printer
Python 2.xは、シーケンスの最後の要素の後にコンマがあると無視します。
>>> a_Tuple_for_instance = (0,1,2,3,)
>>> another_Tuple = (0,1,2,3)
>>> a_Tuple_for_instance == another_Tuple
True
末尾のコンマは、単一の括弧で囲まれた要素をシーケンスとして扱います。
>>> a_Tuple_with_one_element = (8,)
組み込みのメソッドや関数は記述子プロトコルを実装していないため、次のようなことはできません。
>>> class C(object):
... id = id
...
>>> C().id()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: id() takes exactly one argument (0 given)
ただし、これを可能にする小さなバインド記述子を作成できます。
>>> from types import MethodType
>>> class bind(object):
... def __init__(self, callable):
... self.callable = callable
... def __get__(self, obj, type=None):
... if obj is None:
... return self
... return MethodType(self.callable, obj, type)
...
>>> class C(object):
... id = bind(id)
...
>>> C().id()
7414064
関数をクラスで装飾することができます - 関数をクラスインスタンスで置き換える:
class countCalls(object):
""" decorator replaces a function with a "countCalls" instance
which behaves like the original function, but keeps track of calls
>>> @countCalls
... def doNothing():
... pass
>>> doNothing()
>>> doNothing()
>>> print doNothing.timesCalled
2
"""
def __init__ (self, functionToTrack):
self.functionToTrack = functionToTrack
self.timesCalled = 0
def __call__ (self, *args, **kwargs):
self.timesCalled += 1
return self.functionToTrack(*args, **kwargs)
これがPythonのドキュメントのどこにあるのか(あるいはそうでないのか)はわかりませんが、python 2.x(少なくとも2.5と2.6、今試したばかりのもの)では、print
name__ステートメントを括弧で呼び出すことができます。これは、Python 2.xのコードをPython 3.xに簡単に移植できるようにしたい場合に便利です。
例:print('We want Moshiach Now')
はpython 2.5、2.6、および3.xではWe want Moshiach Now
workを表示するはずです。
また、Python 2および3では、not
name__演算子を括弧付きで呼び出すことができます。not False
およびnot(False)
は両方ともTrue
name__を返すはずです。
括弧は他のステートメントや演算子でも機能する可能性があります。
_ edit _ :not
name__演算子(そしておそらく他の演算子)の周りに括弧を置くのは得策ではありません。これは、括弧が実際に1
の周りにあるために起こります。
>>> (not 1) == 9
False
>>> not(1) == 9
True
これは、いくつかの値(これは有効な識別子名ではないと私は思います)についても同様に機能します。not'val'
はFalse
name__を返し、print'We want Moshiach Now'
はWe want Moshiach Now
を返すべきです。 (しかしnot552
は有効な識別子名なのでNameErrorを送出します)。
辞書のすべてのフィールドを初期化するのが面倒ですか?問題ない:
Python> 2.3の場合:
from collections import defaultdict
Pythonの場合<= 2.3:
def defaultdict(type_):
class Dict(dict):
def __getitem__(self, key):
return self.setdefault(key, type_())
return Dict()
どのバージョンでも:
d = defaultdict(list)
for stuff in lots_of_stuff:
d[stuff.name].append(stuff)
更新:
ありがとう Ken Arnold 。私はdefaultdictのより洗練されたバージョンを再実装しました。これは 標準ライブラリのもの とまったく同じように動作します。
def defaultdict(default_factory, *args, **kw):
class defaultdict(dict):
def __missing__(self, key):
if default_factory is None:
raise KeyError(key)
return self.setdefault(key, default_factory())
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.__missing__(key)
return defaultdict(*args, **kw)
Monkeypatchingオブジェクト
Pythonのすべてのオブジェクトは、オブジェクトの属性を格納する__dict__
メンバーを持っています。だから、あなたはこのようなことをすることができます:
class Foo(object):
def __init__(self, arg1, arg2, **kwargs):
#do stuff with arg1 and arg2
self.__dict__.update(kwargs)
f = Foo('arg1', 'arg2', bar=20, baz=10)
#now f is a Foo object with two extra attributes
これは、属性と機能の両方を任意にオブジェクトに追加するために悪用される可能性があります。これを悪用して、手っ取り早いstruct
型を作成することもできます。
class struct(object):
def __init__(**kwargs):
self.__dict__.update(kwargs)
s = struct(foo=10, bar=11, baz="i'm a string!')
シンプルな内蔵ベンチマークツール
Python標準ライブラリには、 "timeit"という非常に使いやすいベンチマークモジュールが付属しています。コマンドラインからそれを使用して、いくつかの言語構成のうちどれが最も速いかを確認することもできます。
例えば。、
% python -m timeit 'r = range(0, 1000)' 'for i in r: pass'
10000 loops, best of 3: 48.4 usec per loop
% python -m timeit 'r = xrange(0, 1000)' 'for i in r: pass'
10000 loops, best of 3: 37.4 usec per loop
これに加えて haridsv によって前述されています。
>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)
これを行うことも可能です:
>>> foo, bar, baz = 1, 2, 3
>>> foo, bar, baz
(1, 2, 3)
リスト内包表記
より伝統的なもの(リストの理解なし)を比較してください。
foo = []
for x in xrange(10):
if x % 2 == 0:
foo.append(x)
に:
foo = [x for x in xrange(10) if x % 2 == 0]
これが2つのイースターエッグです。
1つはpython自体にあります。
>>> import __hello__
Hello world...
Werkzeug
モジュールの中のもう1つのものです。これは明らかにするのは少し複雑です。
Werkzeug
のソースコードを見ることによって、werkzeug/__init__.py
に、あなたの注意を引くべきである行があります:
'werkzeug._internal': ['_easteregg']
少し興味があるなら、werkzeug/_internal.py
を見てください。そこには、引数にwsgiアプリケーションをとる_easteregg()
関数があります。それは、base64でエンコードされたデータと2つの入れ子関数も含みます。クエリ文字列でmacgybarchakku
という名前の引数が見つかった場合、特別なことをするようです。
だから、この復活祭の卵を明らかにするには、アプリケーションを_easteregg()
関数でラップする必要があるようです。
from werkzeug import Request, Response, run_simple
from werkzeug import _easteregg
@Request.application
def application(request):
return Response('Hello World!')
run_simple('localhost', 8080, _easteregg(application))
さて、あなたがアプリを実行し、 http:// localhost:8080 /?macgybarchakku にアクセスすると、イースターエッグが表示されるはずです。
あなたのクラスでディスクリプタを使用している場合、Pythonはそのキーのために__dict__
を完全にバイパスします。
>>> class User(object):
... def _get_username(self):
... return self.__dict__['username']
... def _set_username(self, value):
... print 'username set'
... self.__dict__['username'] = value
... username = property(_get_username, _set_username)
... del _get_username, _set_username
...
>>> u = User()
>>> u.username = "foo"
username set
>>> u.__dict__
{'username': 'foo'}
これはdir()
をきれいに保つのに役立ちます。
Pythonicのイディオムx = ... if ... else ...
はx = ... and ... or ...
よりはるかに優れています。
文は
x = 3 if (y == 1) else 2
と同等です
x = y == 1 and 3 or 2
x = ... and ... or ...
イディオムを使用すると、いつかこの厄介な状況に噛まれる可能性があります。
x = 0 if True else 1 # sets x equal to 0
したがって、と等価ではありません
x = True and 0 or 1 # sets x equal to 1
これを行う正しい方法の詳細については、 Pythonの隠された機能 を参照してください。
可変バッファの公開
Pythonを使用する バッファプロトコル Python(2.5/2.6)の可変バイト指向バッファを公開する.
(申し訳ありません、ここにコードはありません。低レベルC APIまたは既存のアダプタモジュールの使用が必要です)。
getattr
は3番目のパラメーターを取りますgetattr(obj, attribute_name, default)
はこんな感じです:
try:
return obj.attribute
except AttributeError:
return default
ただしattribute_name
は任意の文字列にできます。
これは アヒルの型付けには本当に便利です 。多分あなたは以下のようなものを持っている:
class MyThing:
pass
class MyOtherThing:
pass
if isinstance(obj, (MyThing, MyOtherThing)):
process(obj)
(ところで、isinstance(obj, (a,b))
はisinstance(obj, a) or isinstance(obj, b)
を意味します。)
あなたが新しい種類のものを作るとき、あなたはそれが起こるところはどこでもそのタプルにそれを加える必要があるでしょう。 (この構造は、モジュールをリロードしたり、同じファイルを2つの名前でインポートしたりするときにも問題を引き起こします。それは、認めようとしている以上のことを意味します)。
class MyThing:
processable = True
class MyOtherThing:
processable = True
if getattr(obj, 'processable', False):
process(obj)
継承を追加すると、さらに良くなります。処理可能なオブジェクトの例はすべてから継承できます。
class Processable:
processable = True
しかし、属性を設定するだけで、全員に基本クラスから継承するように説得する必要はありません。
__getattr __()
getattr
は、一般的なクラスを作成するための本当に素晴らしい方法です。これは、APIを書いている場合に特に便利です。たとえば、 FogBugz Python API では、メソッド呼び出しをWebサービスにシームレスに渡すためにgetattr
が使用されます。
class FogBugz:
...
def __getattr__(self, name):
# Let's leave the private stuff to Python
if name.startswith("__"):
raise AttributeError("No such attribute '%s'" % name)
if not self.__handlerCache.has_key(name):
def handler(**kwargs):
return self.__makerequest(name, **kwargs)
self.__handlerCache[name] = handler
return self.__handlerCache[name]
...
誰かがFogBugz.search(q='bug')
を呼び出したとき、彼らは実際にはsearch
メソッドを呼び出しません。代わりに、getattr
は、Web APIへの適切なHTTPリクエストを作成するmakerequest
メソッドをラップする新しい関数を作成することによって呼び出しを処理します。エラーが発生するとWebサービスからディスパッチされ、ユーザーに返されます。
すべてが一流であること(「すべてがオブジェクトであること」)、およびこれが引き起こす可能性がある騒乱。
>>> x = 5
>>> y = 10
>>>
>>> def sq(x):
... return x * x
...
>>> def plus(x):
... return x + x
...
>>> (sq,plus)[y>x](y)
20
最後の行は、2つの関数を含むTupleを作成し、次にy> x(True)を評価し、それをTupleへのインデックスとして(int、1にキャストすることによって)使用し、次にその関数をパラメーターyと共に呼び出して表示します。結果。
さらに悪用するために、インデックス付きのオブジェクト(リストなど)を返す場合は、最後に角括弧を追加することができます。内容が呼び出し可能な場合は、より多くの括弧など。余分な倒錯のために、別の例における式としてこのようなコードの結果を使用してください(すなわち、y> xをこのコードで置き換えてください):
(sq,plus)[y>x](y)[4](x)
これは、Pythonの2つの側面、つまり「すべてはオブジェクトです」という哲学、および言語の構文の不適切または不十分な使用が、単一の式に収まる完全に判読不可能で保守不可能なスパゲッティコードにつながる可能性がある方法を示しています。 。
Forループ、リスト内包表記、ジェネレータ式のタプル展開
>>> l=[(1,2),(3,4)]
>>> [a+b for a,b in l ]
[3,7]
この慣用句では、辞書の(key、data)の組を反復処理するのに役立ちます。
d = { 'x':'y', 'f':'e'}
for name, value in d.items(): # one can also use iteritems()
print "name:%s, value:%s" % (name,value)
プリント:
name:x, value:y
name:f, value:e
わずかな作業で、スレッディングモジュールは驚くほど使いやすくなります。このデコレータは、関数が自身のスレッドで実行されるように関数を変更し、通常の結果ではなくプレースホルダクラスのインスタンスを返します。あなたは、placeolder.resultをチェックすることによって答えを探るか、placeholder.awaitResult()を呼び出すことによってそれを待つことができます
def threadify(function):
"""
exceptionally simple threading decorator. Just:
>>> @threadify
... def longOperation(result):
... time.sleep(3)
... return result
>>> A= longOperation("A has finished")
>>> B= longOperation("B has finished")
A doesn't have a result yet:
>>> print A.result
None
until we wait for it:
>>> print A.awaitResult()
A has finished
we could also wait manually - half a second more should be enough for B:
>>> time.sleep(0.5); print B.result
B has finished
"""
class thr (threading.Thread,object):
def __init__(self, *args, **kwargs):
threading.Thread.__init__ ( self )
self.args, self.kwargs = args, kwargs
self.result = None
self.start()
def awaitResult(self):
self.join()
return self.result
def run(self):
self.result=function(*self.args, **self.kwargs)
return thr
Pythonは非常に予想外のことに例外があります。
輸入
これは、ライブラリが見つからない場合に代替をインポートすることを可能にします
try:
import json
except ImportError:
import simplejson as json
繰り返し
Forループはこれを内部で行い、StopIterationをキャッチします。
iter([]).next()
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
iter(a).next()
StopIteration
アサーション
>>> try:
... assert []
... except AssertionError:
... print "This list should not be empty"
This list should not be empty
これは1つのチェックに対してより冗長ですが、同じエラーメッセージを持つ例外とブール演算子を混在させる複数のチェックは、この方法で短縮できます。
Pythonには秘密がありません;)
印刷機能と解凍を組み合わせます。
# in 2.6 <= python < 3.0, 3.0 + the print function is native
from __future__ import print_function
mylist = ['foo', 'bar', 'some other value', 1,2,3,4]
print(*mylist)
オブジェクトインスタンスのメソッド置換
すでに作成されているオブジェクトインスタンスのメソッドを置き換えることができます。それはあなたが異なる(例外的な)機能を持つオブジェクトインスタンスを作成することを可能にします:
>>> class C(object):
... def fun(self):
... print "C.a", self
...
>>> inst = C()
>>> inst.fun() # C.a method is executed
C.a <__main__.C object at 0x00AE74D0>
>>> instancemethod = type(C.fun)
>>>
>>> def fun2(self):
... print "fun2", self
...
>>> inst.fun = instancemethod(fun2, inst, C) # Now we are replace C.a by fun2
>>> inst.fun() # ... and fun2 is executed
fun2 <__main__.C object at 0x00AE74D0>
inst
インスタンスでC.a
はfun2()
に置き換えられました(self
は変更されませんでした)。
代わりにnew
モジュールを使用することもできますが、Python 2.6以降は推奨されなくなりました。
>>> def fun3(self):
... print "fun3", self
...
>>> import new
>>> inst.fun = new.instancemethod(fun3, inst, C)
>>> inst.fun()
fun3 <__main__.C object at 0x00AE74D0>
ノード: /この解決策は、継承メカニズムの一般的な置き換えとしては使用しないでください。しかし、それはいくつかの特定の状況(デバッグ、モック)でとても便利かもしれません。
警告: この解決法は組み込み型やスロットを使った新しいスタイルクラスには使えません。
Pythonの動的な性質を利用して、アプリ構成ファイルをpython構文で作成します。たとえば、設定ファイルに次のものがあるとします。
{
"name1": "value1",
"name2": "value2"
}
それならあなたはそれを自明に読むことができます:
config = eval(open("filename").read())
ディクショナリ要素に属性(プロパティ)としてアクセスします。したがって、a1 = AttrDict()がa1 ['name']の代わりにキー 'name' - >を持つ場合、 - > a1.nameを使用してa1のname属性に簡単にアクセスできます。
class AttrDict(dict):
def __getattr__(self, name):
if name in self:
return self[name]
raise AttributeError('%s not found' % name)
def __setattr__(self, name, value):
self[name] = value
def __delattr__(self, name):
del self[name]
person = AttrDict({'name': 'John Doe', 'age': 66})
print person['name']
print person.name
person.name = 'Frodo G'
print person.name
del person.age
print person
特別な方法
Python 3のUnicode識別子
>>> 'Unicode字符_تكوين_Variable'.isidentifier()
True
>>> Unicode字符_تكوين_Variable='Python3 rules!'
>>> Unicode字符_تكوين_Variable
'Python3 rules!'
モジュールは _ everything _ を名前空間にエクスポートします
他のモジュールからインポートされた名前を含みます。
# this is "answer42.py"
from operator import *
from inspect import *
モジュールからインポート可能なものをテストしましょう。
>>> import answer42
>>> answer42.__dict__.keys()
['gt', 'imul', 'ge', 'setslice', 'ArgInfo', 'getfile', 'isCallable', 'getsourcelines', 'CO_OPTIMIZED', 'le', 're', 'isgenerator', 'ArgSpec', 'imp', 'lt', 'delslice', 'BlockFinder', 'getargspec', 'currentframe', 'CO_NOFREE', 'namedtuple', 'rshift', 'string', 'getframeinfo', '__file__', 'strseq', 'iconcat', 'getmro', 'mod', 'getcallargs', 'isub', 'getouterframes', 'isdatadescriptor', 'modulesbyfile', 'setitem', 'truth', 'Attribute', 'div', 'CO_NESTED', 'ixor', 'getargvalues', 'ismemberdescriptor', 'getsource', 'isMappingType', 'eq', 'index', 'xor', 'sub', 'getcomments', 'neg', 'getslice', 'isframe', '__builtins__', 'abs', 'getmembers', 'mul', 'getclasstree', 'irepeat', 'is_', 'getitem', 'indexOf', 'Traceback', 'findsource', 'ModuleInfo', 'ipow', 'TPFLAGS_IS_ABSTRACT', 'or_', 'joinseq', 'is_not', 'itruediv', 'getsourcefile', 'dis', 'os', 'iand', 'countOf', 'getinnerframes', 'pow', 'pos', 'and_', 'lshift', '__name__', 'sequenceIncludes', 'isabstract', 'isbuiltin', 'invert', 'contains', 'add', 'isSequenceType', 'irshift', 'types', 'tokenize', 'isfunction', 'not_', 'istraceback', 'getmoduleinfo', 'isgeneratorfunction', 'getargs', 'CO_GENERATOR', 'cleandoc', 'classify_class_attrs', 'EndOfBlock', 'walktree', '__doc__', 'getmodule', 'isNumberType', 'ilshift', 'ismethod', 'ifloordiv', 'formatargvalues', 'indentsize', 'getmodulename', 'inv', 'Arguments', 'iscode', 'CO_NEWLOCALS', 'formatargspec', 'iadd', 'getlineno', 'imod', 'CO_VARKEYWORDS', 'ne', 'idiv', '__package__', 'CO_VARARGS', 'attrgetter', 'methodcaller', 'truediv', 'repeat', 'trace', 'isclass', 'ior', 'ismethoddescriptor', 'sys', 'isroutine', 'delitem', 'stack', 'concat', 'getdoc', 'getabsfile', 'ismodule', 'linecache', 'floordiv', 'isgetsetdescriptor', 'itemgetter', 'getblock']
>>> from answer42 import getmembers
>>> getmembers
<function getmembers at 0xb74b2924>
>>>
from x import *
を定義し、__all__ =
を定義しないのは良い理由です。
挿入と追加
機能ではありませんが、面白いかもしれません
リストにデータを挿入してから元に戻すとします。最も簡単なことは
count = 10 ** 5
nums = []
for x in range(count):
nums.append(x)
nums.reverse()
それならあなたは思います:最初から数字を挿入することについてはどうでしょうか?そう:
count = 10 ** 5
nums = []
for x in range(count):
nums.insert(0, x)
しかし、それは100倍遅くなります! count = 10 ** 6と設定すると、1,000倍遅くなります。これは、insertがO(n ^ 2)であり、appendがO(n)であるためです。
その違いの理由は、insertが呼び出される度にinsertがリストの各要素を移動しなければならないからです。リストの最後にその要素を追加するだけです(すべてを再割り当てする必要がある場合もありますが、それでもはるかに高速です)。
同じ値に複数の変数を割り当てることができます
>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)
コンパクトな方法で、いくつかの変数をNoneに初期化するのに便利です。
Andまたはorを使用して3次演算子をシミュレートします。
および/またはpythonの演算子は、ブール値ではなくオブジェクト自体を返します。したがって:
In [18]: a = True
In [19]: a and 3 or 4
Out[19]: 3
In [20]: a = False
In [21]: a and 3 or 4
Out[21]: 4
しかし、Py 2.5は明示的な三次演算子を追加したようです
In [22]: a = 5 if True else '6'
In [23]: a
Out[23]: 5
まあ、これはあなたの本当の節が偽に評価されないことをあなたが確信しているならば働きます。例:
>>> def foo():
... print "foo"
... return 0
...
>>> def bar():
... print "bar"
... return 1
...
>>> 1 and foo() or bar()
foo
bar
1
正しく理解するためには、もう少し手を加えてください。
>>> (1 and [foo()] or [bar()])[0]
foo
0
しかし、これはそれほどきれいではありません。ご使用のバージョンのpythonでサポートされている場合は、条件演算子を使用してください。
>>> foo() if True or bar()
foo
0
複数行の文字列を一度に1画面ずつ印刷する
license
オブジェクトがインスタンスであるsite._Printer
クラスに隠されている、あまり実用的な機能ではありません。後者が呼ばれると、Pythonライセンスを表示します。文字列を渡して、同じ型の別のオブジェクトを作成することができます。ファイルの内容 - 2番目の引数として、それを呼び出します。
type(license)(0,open('textfile.txt').read(),0)()
これは、一度に一定の行数で分割されたファイルの内容を表示します。
...
file row 21
file row 22
file row 23
Hit Return for more, or q (and Return) to quit:
すべてが動的です
「コンパイル時はありません」。 Pythonのすべてはランタイムです。モジュールは、スクリプトのように、モジュールのソースを上から下に実行することによって「定義」され、その結果の名前空間はモジュールの属性スペースです。同様に、クラスはクラス本体を上から下に実行することによって「定義」され、結果のネームスペースはクラスの属性スペースになります。クラス本体には、importステートメント、ループ、その他のクラスステートメントを含む、完全に任意のコードを含めることができます。クラス、関数、あるいはモジュールさえも '動的に'作成することは時々求められますが、難しいことではありません。実際、すべてが「動的」であるため、避けることは不可能です。
二重下線で始まっていて終わらない変数は、慣例に従ってではなく、非公開になります。実際には、__ varは_Classname__varに変わります。ここで、Classnameは、変数が作成されたクラスです。それらは継承されず、上書きすることはできません。
>>> class A:
... def __init__(self):
... self.__var = 5
... def getvar(self):
... return self.__var
...
>>> a = A()
>>> a.__var
Traceback (most recent call last):
File "", line 1, in
AttributeError: A instance has no attribute '__var'
>>> a.getvar()
5
>>> dir(a)
['_A__var', '__doc__', '__init__', '__module__', 'getvar']
>>>
EVERYTHINGがオブジェクトであり、それ自体が拡張可能であるという事実。定義した関数に、メタデータとしてメンバー変数を追加できます。
>>> def addInts(x,y):
... return x + y
>>> addInts.params = ['integer','integer']
>>> addInts.returnType = 'integer'
これは動的な単体テストを書くのにとても便利です。
ブール値コンテキストのオブジェクト
空のタプル、リスト、辞書、文字列、およびその他の多くのオブジェクトは、ブール値のコンテキストではFalseと同等です(空でない場合はTrueと同等です)。
empty_Tuple = ()
empty_list = []
empty_dict = {}
empty_string = ''
empty_set = set()
if empty_Tuple or empty_list or empty_dict or empty_string or empty_set:
print 'Never happens!'
これは論理演算がTrue/Falseの代わりにそのオペランドの1つを返すことを可能にします。これは状況によっては有用です:
s = t or "Default value" # s will be assigned "Default value"
# if t is false/empty/none
Pickleを介してユーザが保存したファイルをロードするアプリケーションのクラスの名前を変更した場合、名前を変更したクラスの1つがユーザの古い保存に保存されていると、そのピクルスファイルにロードできません。
ただし、クラス定義への参照を追加するだけで、すべてがうまくいきます。
例:
class Bleh:
pass
今、
class Blah:
pass
そのため、ユーザーのピクルス保存ファイルにはBlehへの参照が含まれていますが、名前の変更のために存在しません。修正は?
Bleh = Blah
簡単です!
機能サポート。
特にジェネレータとジェネレータ式。
Rubyが再びこの主流を作りましたが、Pythonも同様にそれを行うことができます。 Rubyのようにライブラリのいたるところにあるわけではありませんが、これは残念ですが、私はシンタックスが好きで、より単純です。
それらはどこにでもあるわけではないので、私はそれらがなぜ有用であるかについて多くの例をそこには見ていないが、それらは私がより清潔でより効率的なコードを書くことを可能にした。
Pythonには、アンダースコアで始まる名前を付けることによってクラスの外部APIの一部になることを意図していないメソッドやその他のクラスメンバーを示すという共通の慣用句があります。これは便利で実際には非常にうまく機能しますが、Pythonはプライベートコードやデータの真のカプセル化をサポートしていないという誤った印象を与えます。実際、Pythonは自動的に 字句クロージャー を提供します。これにより、状況が本当に保証する場合、データをはるかに安全な方法でカプセル化することが非常に簡単になります。これはこのテクニックを利用するクラスの考案された例です:
class MyClass(object):
def __init__(self):
privateData = {}
self.publicData = 123
def privateMethod(k):
print privateData[k] + self.publicData
def privilegedMethod():
privateData['foo'] = "hello "
privateMethod('foo')
self.privilegedMethod = privilegedMethod
def publicMethod(self):
print self.publicData
そして、これがその使用法の一例です。
>>> obj = MyClass()
>>> obj.publicMethod()
123
>>> obj.publicData = 'World'
>>> obj.publicMethod()
World
>>> obj.privilegedMethod()
hello World
>>> obj.privateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'privateMethod'
>>> obj.privateData
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'privateData'
重要なのは、privateMethod
とprivateData
は実際にはまったくobjの属性ではないため、外部からアクセスすることはできず、dir()
のように表示されることもありません。これらはコンストラクタ内のローカル変数で、__init__
以外では完全にアクセスできない。ただし、クロージャの魔法のため、(この例では)privilegedMethod
を呼び出して以外にアクセスする方法はありませんが、実際にはそれらは関連付けられているオブジェクトと同じ有効期間を持つインスタンスごとの変数です。この種の非常に厳密なカプセル化はやり過ぎることが多いですが、APIや名前空間をきれいに保つために本当に便利なことがあります。
Python 2.xでは、可変プライベート状態を持つ唯一の方法は可変オブジェクトを使うことです(この例のdictのように)。多くの人がこれがどれほど厄介である可能性があるかについて述べました。 Python 3.xは PEP 3104 に記述されているnonlocal
キーワードを導入することによってこの制限を取り除きます。
キーが辞書に入っているかどうかをテストする簡単な方法:
>>> 'key' in { 'key' : 1 }
True
>>> d = dict(key=1, key2=2)
>>> if 'key' in d:
... print 'Yup'
...
Yup
** Using sets to reference contents in sets of frozensets**
ご存じのとおり、集合は可変であるためハッシュできないため、集合のセットを作成する場合(または集合を辞書のキーとして使用する場合)、Frozensetを使用する必要があります。
>>> fabc = frozenset('abc')
>>> fxyz = frozenset('xyz')
>>> mset = set((fabc, fxyz))
>>> mset
{frozenset({'a', 'c', 'b'}), frozenset({'y', 'x', 'z'})}
ただし、メンバーシップをテストし、通常のセットだけを使用してメンバーを削除/破棄することは可能です。
>>> abc = set('abc')
>>> abc in mset
True
>>> mset.remove(abc)
>>> mset
{frozenset({'y', 'x', 'z'})}
Python標準ライブラリのドキュメントから引用するには:
__contains__()
、remove()
、およびdiscard()
メソッドへのelem
引数はセットであるかもしれないことに注意してください。同等の凍結セットの検索をサポートするために、検索中にelem
セットが一時的に変更されてから復元されます。検索中、elem
セットは意味のある値を持っていないので、読んだり変更したりしないでください。
残念ながら、そしておそらく驚くべきことに、同じことが辞書には当てはまりません。
>>> mdict = {fabc:1, fxyz:2}
>>> fabc in mdict
True
>>> abc in mdict
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: unhashable type: 'set'
Getattr組み込み関数
>>> class C():
def getMontys(self):
self.montys = ['Cleese','Palin','Idle','Gilliam','Jones','Chapman']
return self.montys
>>> c = C()
>>> getattr(c,'getMontys')()
['Cleese', 'Palin', 'Idle', 'Gilliam', 'Jones', 'Chapman']
>>>
状況に応じて関数をディスパッチしたい場合に便利です。 Dive Into Python( ここ )の例を参照してください。
Nick Johnsonによる Propertyクラス の実装(単なる記述子のデモンストレーション、もちろん組み込み関数の置き換えではありません)については、AttributeErrorを発生させるセッターを含めます。
classプロパティ(オブジェクト): def __init __(self、fget): self.fget = fget def。__get __(self、obj) objがNoneの場合: selfを返す selfを返す def __set __(self、obj、 value): AttributeError、 '読み取り専用属性'を発生させます
セッターを含めると、メソッド/非データ記述子とは対照的に、これがデータ記述子になります。データ記述子はインスタンス辞書よりも優先されます。インスタンスはプロパティ名に別のオブジェクトを割り当てることができなくなり、プロパティに割り当てようとすると属性エラーが発生します。
>>> float('infinity')
inf
>>> float('NaN')
nan
より詳しい情報:
本当に隠された機能ではありませんが、便利になるかもしれない何か。
リスト内の項目をペアでループするため
for x, y in Zip(s, s[1:]):
spam
モジュールテスト目的で使用されます。
ctypes
チュートリアル から選んだ。自分で試してみてください。
>>> import __hello__
Hello world...
>>> type(__hello__)
<type 'module'>
>>> from __phello__ import spam
Hello world...
Hello world...
>>> type(spam)
<type 'module'>
>>> help(spam)
Help on module __phello__.spam in __phello__:
NAME
__phello__.spam
FILE
c:\python26\<frozen>
関数内でexec
を使用すると、変数検索の規則が劇的に変わります。クロージャはもはや不可能ですが、Pythonでは関数内で任意の識別子を使用できます。これはあなたに "変更可能なlocals()"を与え、識別子をスターインポートするために使うことができます。欠点は、変数がフレーム内のスロットではなく辞書に入るため、すべての検索が遅くなることです。
>>> def f():
... exec "a = 42"
... return a
...
>>> def g():
... a = 42
... return a
...
>>> import dis
>>> dis.dis(f)
2 0 LOAD_CONST 1 ('a = 42')
3 LOAD_CONST 0 (None)
6 DUP_TOP
7 EXEC_STMT
3 8 LOAD_NAME 0 (a)
11 RETURN_VALUE
>>> dis.dis(g)
2 0 LOAD_CONST 1 (42)
3 STORE_FAST 0 (a)
3 6 LOAD_FAST 0 (a)
9 RETURN_VALUE
メモリ管理
Pythonは動的にメモリを割り当て、ガベージコレクションを使って未使用スペースを回復します。オブジェクトが範囲外になり、他の変数がそのオブジェクトを参照しなくなると、そのオブジェクトは回復されます。私は、バッファオーバーランやゆっくりと成長するサーバープロセスについて心配する必要はありません。メモリ管理は他の動的言語の機能でもありますが、Pythonはそれをうまく実行します。
もちろん、循環参照には注意し、不要になったオブジェクトへの参照を維持する必要がありますが、弱い参照はここでは大いに役立ちます。
第一級オブジェクトとしてのクラス(動的クラス定義で表示)
クロージャーの使用にも注意してください。この特定の例が問題に対する「正しい」アプローチのように見える場合は、慎重に再検討してください...数回:)
def makeMeANewClass(parent, value):
class IAmAnObjectToo(parent):
def theValue(self):
return value
return IAmAnObjectToo
Klass = makeMeANewClass(str, "fred")
o = Klass()
print isinstance(o, str) # => True
print o.theValue() # => fred
これまでは範囲(INT)ではなくxrange(INT)を使用していました。メモリ使用量が少なくなり、整数のサイズには依存しません。ええ!それは良くないですか?
まったく隠された機能ではありませんが、それでも素晴らしい:
import os.path as op
root_dir = op.abspath(op.join(op.dirname(__file__), ".."))
パスを操作するときにたくさんの文字を節約します!
mapとreduce関数を使ったmapreduce
このようにして単純な副産物を作成します。
def sumprod(x,y):
return reduce(lambda a,b:a+b, map(lambda a, b: a*b,x,y))
例:
In [2]: sumprod([1,2,3],[4,5,6])
Out[2]: 32
>>> x=[1,1,2,'a','a',3]
>>> y = [ _x for _x in x if not _x in locals()['_[1]'] ]
>>> y
[1, 2, 'a', 3]
"locals()['_ [1]']"は作成中のリストの "秘密の名前"です。構築中のリストの状態がその後の構築決定に影響を与える場合に非常に役立ちます。
プログラミング機能ではありませんが、Pythonをbash
またはShell scripts
と共に使用する場合に便利です。
python -c"import os; print(os.getcwd());"
pythonのドキュメントはこちら を参照してください。 より長いPythonスクリプト を書くときに注意すべき追加事項は このディスカッション で見ることができます。
Pythonの位置展開とキーワード展開は、格納されているリストからだけでなく、その場で使用できます。
l=lambda x,y,z:x+y+z
a=1,2,3
print l(*a)
print l(*[a[0],2,3])
これは通常、次のようなものでより便利です。
a=[2,3]
l(*(a+[3]))
スクリプト(およびdoctest文字列)の対話型デバッグ
これほど広く知られているとは思いませんが、Pythonスクリプトに次の行を追加してください。
import pdb; pdb.set_trace()
コード内のその時点でPDBデバッガーに実行カーソルが表示されます。それほど知られていないことは、doctestで同じ行を使用できるということです。
"""
>>> 1 in (1,2,3)
Becomes
>>> import pdb; pdb.set_trace(); 1 in (1,2,3)
"""
その後、デバッガを使ってdoctest環境をチェックアウトできます。各行はそれぞれ独立して実行されるため、doctestを実際に実行することはできませんが、doctestのglobおよび環境をデバッグするための優れたツールです。
commands.getoutput
os.system
の場合のようにstdout
またはstderr
に直接出力する関数の出力を取得したい場合は、 commands.getoutput
が役立ちます。モジュール全体は素晴らしいものでできています。
>>> print commands.getoutput('ls')
myFile1.txt myFile2.txt myFile3.txt myFile4.txt myFile5.txt
myFile6.txt myFile7.txt myFile8.txt myFile9.txt myFile10.txt
myFile11.txt myFile12.txt myFile13.txt myFile14.txt module.py
Python 2では、バッククォートで囲むことで式の文字列表現を生成できます。
>>> `sorted`
'<built-in function sorted>'
これはpython 3.Xではなくなりました。
必要に応じて関数kwargsを構築できます。
kwargs = {}
kwargs[str("%s__icontains" % field)] = some_value
some_function(**kwargs)
Pythonはそれ以外の場合は文字列ではないと文句を言うので、str()呼び出しはどういうわけか必要です。理由はわかりません;)Djangosオブジェクトモデル内の動的フィルタにこれを使用します。
result = model_class.objects.filter(**kwargs)
reduceとoperatorを使ったいくつかの素晴らしい機能。
>>> from operator import add,mul
>>> reduce(add,[1,2,3,4])
10
>>> reduce(mul,[1,2,3,4])
24
>>> reduce(add,[[1,2,3,4],[1,2,3,4]])
[1, 2, 3, 4, 1, 2, 3, 4]
>>> reduce(add,(1,2,3,4))
10
>>> reduce(mul,(1,2,3,4))
24
これは型エラーをデバッグするときに私が使う便利な関数です。
def typePrint(object):
print(str(object) + " - (" + str(type(object)) + ")")
それは単に入力に続いて型を表示します、例えば
>>> a = 101
>>> typePrint(a)
101 - (<type 'int'>)
文字列を乗算して繰り返します
print "SO"*5
与える
SOSOSOSOSO