Python'un gizli özellikleri [kapalı]

30 ответов

Zincirleme karşılaştırma mevsim:

>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20 
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True

, True olarak ortaya çıkan 1 < x yi yaptığını ve daha sonra True < 10 olan True < 10 yi karşılaştırdığını düşünüyorsanız, o zaman hayır, gerçekten ne olmaz (son örneğe bakın.) Gerçekten 1 < x and x < 10 ve x < 10 and 10 < x * 10 and x*10 < 100 olarak tercüme ediyor, ancak daha az yazarak ve her terim yalnızca bir kez değerlendiriliyor.

741
cevap Thomas Wouters 2012-01-18 20:23:50
kaynak

, regex'inizi hata ayıklamak için python regex ayrıştırma ağacını alın.

düzenli ifadeler python'un harika bir özelliğidir, ancak bunları hata ayıklama bir acı olabilir ve bir regex yanlışını elde etmek çok kolaydır.

Neyse ki, python belgesiz, deneysel, gizli bayrak re.DEBUG (aslında, 128) re.compile geçerek, regex ayrıştırma ağacı yazdırabilirsiniz .

>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
    re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
  subpattern None
    literal 61
    subpattern 1
      in
        literal 45
        literal 43
      max_repeat 1 2
        in
          range (48, 57)
literal 93
subpattern 2
  min_repeat 0 65535
    any None
in
  literal 47
  literal 102
  literal 111
  literal 110
  literal 116

anladığınızda sözdizimi, hatalarınızı tespit edebilirsiniz. Orada [/font] de [] kaçmak unuttum görebilirsiniz .

tabii ki, regexes gibi istediğiniz bayraklarla birleştirebilirsiniz:

>>> re.compile("""
 ^              # start of a line
 \[font         # the font tag
 (?:=(?P<size>  # optional [font=+size]
 [-+][0-9]{1,2} # size specification
 ))?
 \]             # end of tag
 (.*?)          # text between the tags
 \[/font\]      # end of the tag
 """, re.DEBUG|re.VERBOSE|re.DOTALL)
512
cevap BatchyX 2012-03-06 18:28:47
kaynak

numaralandır

numaralandırmayla yinelenebilir bir sarın ve öğeyi diziniyle birlikte verir.

örneğin:


>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>

Referanslar:

460
cevap Dave 2010-07-14 12:39:06
kaynak

oluşturma jeneratörler nesneleri

Eğer

yazarsanız
x=(n for n in foo if bar(n))

jeneratörü çıkarabilir ve X'e atayabilirsiniz. Şimdi

yapabileceğiniz anlamına geliyor
for n in x:

bunun avantajı,

yaptıysanız ihtiyacınız olan ara depolamaya ihtiyacınız olmamasıdır
x = [n for n in foo if bar(n)]

bazı durumlarda bu önemli bir hıza yol açabilir.

yapabilirsiniz temel olarak döngüler için iç içe geçmiş çoğaltarak, jeneratörün sonuna kadar birçok ıf ifadesi ekleyin:

>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
...   print i 

(0, 4)
(0, 5)
(1, 4)
(1, 5)
419
cevap freespace 2009-11-23 17:36:53
kaynak

'() çağrılabilir bir argüman alabilir

örneğin:

def seek_next_line(f):
    for c in iter(lambda: f.read(1),'\n'):
        pass

iter(callable, until_value) işlevi defalarca callable çağırır ve until_value dönene kadar sonucunu verir.

353
cevap mbac32768 2010-05-28 19:06:07
kaynak

değiştirilebilir varsayılan argümanlarla dikkatli olun

>>> def foo(x=[]):
...     x.append(1)
...     print x
... 
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]

yerine, "verilmeyen" belirten bir sentinel değeri kullanmanız ve varsayılan olarak istediğiniz değiştirilebilir ile değiştirmeniz gerekir:

>>> def foo(x=None):
...     if x is None:
...         x = []
...     x.append(1)
...     print x
>>> foo()
[1]
>>> foo()
[1]
339
cevap Jason Baker 2010-07-14 06:12:47
kaynak

jeneratör işlevlerine değer gönderme . Örneğin bu işleve sahip olmak:

def mygen():
    """Yield 5 until something else is passed back via send()"""
    a = 5
    while True:
        f = (yield a) #yield a and possibly get f in return
        if f is not None: 
            a = f  #store the new value

şunları yapabilirsiniz:

>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7)  #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7
317
cevap Rafał Dowgird 2011-04-11 01:54:30
kaynak

kapsamları belirtmek için boşluk kullanmayı sevmiyorsanız,

vererek c stili {} kullanabilirsiniz
from __future__ import braces
314
cevap eduffy 2008-09-22 02:01:53
kaynak

dilim işleçleri adım bağımsız değişkeni. Örneğin:

a = [1,2,3,4,5]
>>> a[::2]  # iterate over the whole list in 2-increments
[1,3,5]

özel durum x[::-1] 'x' için yararlı bir deyim.

>>> a[::-1]
[5,4,3,2,1]
305
cevap Rafał Dowgird 2008-09-19 17:33:42
kaynak

Dekoratörler

Dekoratörler , işlevsellik ekleyebilen, bağımsız değişkenleri veya sonuçları değiştirebilen başka bir işleve bir işlev veya yöntemi sarmaya izin verir. Bir "at" işareti (@) ile başlayan işlev tanımının üstünde dekoratörler bir satır yazarsınız.

örneği, dekore edilmiş işlevin argümanlarını çağırmadan önce basan print_args dekoratörünü gösterir:

>>> def print_args(function):
>>>     def wrapper(*args, **kwargs):
>>>         print 'Arguments:', args, kwargs
>>>         return function(*args, **kwargs)
>>>     return wrapper

>>> @print_args
>>> def write(text):
>>>     print text

>>> write('foo')
Arguments: ('foo',) {}
foo
289
cevap DzinX 2010-04-15 20:18:11
kaynak

için...else sözdizimi (bkz. http://docs.python.org/ref/for.html )

for i in foo:
    if i == 0:
        break
else:
    print("i was never 0")

"else" bloğu, mola çağrılmadığı sürece normalde for döngüsünün sonunda yürütülür.

yukarıdaki kod aşağıdaki gibi taklit edilebilir:

found = False
for i in foo:
    if i == 0:
        found = True
        break
if not found: 
    print("i was never 0")
288
cevap rlerallut 2011-04-11 01:57:34
kaynak

2.5 itibaren dicts eksik öğeler için çağrılan özel bir yöntem __missing__ var:

>>> class MyDict(dict):
...  def __missing__(self, key):
...   self[key] = rv = []
...   return rv
... 
>>> m = MyDict()
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

hemen hemen aynı şeyi defaultdict olarak adlandırılan collections de bir dict alt sınıfı da vardır, ancak mevcut öğeler için bağımsız değişkenler olmadan bir işlev çağırır:

>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}

bu tür alt sınıfları beklemeyen işlevlere geçmeden önce bu tür dict'leri düzenli dictlere dönüştürmenizi öneririm. Bir çok kod kullanır d[a_key] ve dict yeni bir öğe eklemek bir öğe olup olmadığını kontrol etmek için KeyErrors yakalar.

258
cevap Armin Ronacher 2008-09-22 01:54:12
kaynak

yerine değer değişimi

>>> a = 10
>>> b = 5
>>> a, b
(10, 5)

>>> a, b = b, a
>>> a, b
(5, 10)

ödevin sağ tarafı yeni bir tuple oluşturan bir ifadedir. Ödevin sol tarafı, a ve b isimlerine (referanssız) tuple'ı hemen açar .

atamadan sonra, yeni tuple unreferenced ve çöp toplama için işaretlenmiş ve a ve b bağlı değerler olmuştur değiştiriyordu.

veri yapıları ,

üzerinde Python öğretici bölümünde belirtildiği gibi

çoklu atama gerçekten tuple ambalaj ve sıra açma sadece bir kombinasyonu olduğunu unutmayın.

247
cevap Lucas S. 2010-04-06 05:40:30
kaynak

'normal ifadeler

Python'da düzenli bir ifadeyi birden fazla satıra bölebilir, eşlemelerinizi adlandırabilir ve yorum ekleyebilirsiniz.

örnek ayrıntılı sözdizimi ( Python dalış):

>>> pattern = """
... ^                   # beginning of string
... M{0,4}              # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                     #            or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                     #        or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                     #        or 5-8 (V, followed by 0 to 3 I's)
... $                   # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)

örnek adlandırma eşleşmeleri ( normal ifade ' dan)

>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'

ayrıca ayrıntılı olarak yapabilirsiniz string literal concatenation sayesinde re.VERBOSE kullanmadan bir regex yazın.

>>> pattern = (
...     "^"                 # beginning of string
...     "M{0,4}"            # thousands - 0 to 4 M's
...     "(CM|CD|D?C{0,3})"  # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
...                         #            or 500-800 (D, followed by 0 to 3 C's)
...     "(XC|XL|L?X{0,3})"  # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
...                         #        or 50-80 (L, followed by 0 to 3 X's)
...     "(IX|IV|V?I{0,3})"  # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
...                         #        or 5-8 (V, followed by 0 to 3 I's)
...     "$"                 # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"
235
cevap user18044 2012-08-04 05:54:45
kaynak

işlev argümanı

açma

bir liste veya * ve ** kullanarak işlev bağımsız değişkenleri olarak bir sözlük açabilirsiniz.

örneğin:

def draw_point(x, y):
    # do some magic

point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}

draw_point(*point_foo)
draw_point(**point_bar)

çok kullanışlı, çünkü listeler, tuples ve dicts konteynerler olarak yaygın olarak kullanılmaktadır.

222
cevap e-satis 2010-06-23 16:13:20
kaynak

ROT13, kod dosyasının üst kısmındaki doğru kodlama bildirimini kullandığınızda, kaynak kodu için geçerli bir kodlamadır:

#!/usr/bin/env python
# -*- coding: rot13 -*-

cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")
205
cevap André 2009-06-22 00:35:44
kaynak

tamamen dinamik bir şekilde yeni türler oluşturma

>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"

ile tam olarak aynı olan

>>> class NewType(object):
>>>     x = "hello"
>>> n = NewType()
>>> n.x
"hello"

muhtemelen en yararlı şey değil, ama bilmek güzel.

Düzenle : yeni türün sabit adı, NewType ifadesiyle aynı şey olması için NewType olmalıdır.

Düzenle : Başlığı daha doğru bir şekilde ayarlayın özelliği açıklayın.

183
cevap Torsten Marek 2012-01-18 20:23:08
kaynak

bağlam yöneticileri ve " with "ifadesi

tanıtılan PEP 343 , bir bağlam yöneticisi ifadeleri paketi için çalışma zamanı bağlamı olarak hareket eden bir nesnedir.

özelliği yeni anahtar kelimeler kullandığından, yavaş yavaş tanıtıldı: Python 2.5 __future__ yönergesi aracılığıyla kullanılabilir. Python 2.6 ve yukarıdaki (Python 3 dahil) varsayılan olarak kullanılabilir.

1519120920 ' ifadesini "1519130920" ifadesiyle kullandım çünkü çok yararlı bir yapı olduğunu düşünüyorum, burada hızlı bir demo:

from __future__ import with_statement

with open('foo.txt', 'w') as f:
    f.write('hello!')

burada perde arkasında neler oluyor, "ifadesi ile __enter__ ve __exit__ yöntemleri dosya nesnesi üzerinde çağırır. İstisna ayrıntıları, varsa __exit__ e de geçirilir Özel Durum, Özel durum işleme orada gerçekleşmesi için izin veren deyim gövdesinden yükseltildi.

bu, bu özel durumda sizin için yaptığı şey, with paketinin kapsamı dışına düştüğünde, normal olarak gerçekleşip gerçekleşmediğine veya bir özel durumun atılıp oluşturulmadığına bakılmaksızın dosyanın kapandığını garanti etmesidir. Temelde ortak istisna işleme kodunu soyutlamanın bir yoludur.

bunun için diğer yaygın kullanım durumları şunlardır iş parçacığı ve veritabanı hareketleri ile kilitleme.

179
cevap Ycros 2010-04-06 06:02:02
kaynak

sözlükleri bir get () yöntemi

var

sözlükleri 'get ()' yöntemine sahiptir. D['key'] yaparsanız ve anahtar orada değilse, bir istisna alırsınız. D yaparsan.eğer'anahtar' orada değilse ('anahtar') almak, geri almak Yok. Bu öğeyi hiçbiri yerine geri almak için ikinci bir argüman ekleyebilirsiniz, örneğin: d.al('anahtar', 0).

sayıları eklemek gibi şeyler için harika:

sum[value] = sum.get(value, 0) + 1

168
cevap Rory 2012-01-18 20:22:41
kaynak

tanımlayıcılar

onlar çekirdek Python özellikleri bir sürü arkasındaki sihirli konum.

üye aramak için noktalı erişim kullandığınızda (örneğin, x.y), Python önce örnek sözlüğündeki üyeyi arar. Bulunmazsa, sınıf sözlüğünde arar. Sınıf sözlüğünde bulursa ve nesne tanımlayıcısı protokolünü uygular, sadece döndürmek yerine Python yürütür. Bir tanımlayıcı herhangi bir sınıftır __get__ , __set__ veya __delete__ yöntemlerini uygular.

işte tanımlayıcıları kullanarak mülkün kendi (salt okunur) sürümünü nasıl uygulayacağınız:

class Property(object):
    def __init__(self, fget):
        self.fget = fget

    def __get__(self, obj, type):
        if obj is None:
            return self
        return self.fget(obj)

ve bunu yerleşik özellik () gibi kullanırsınız:

class MyClass(object):
    @Property
    def foo(self):
        return "Foo!"

tanımlayıcıları özellikleri, bağlı yöntemler, statik yöntemler, sınıf yöntemleri ve yuvaları, diğer şeylerin yanı sıra uygulamak için Python'da kullanılır. Onları anlamak neden görmek kolaylaştırır daha önce Python 'tuhaflıklar' gibi görünen bir çok şey, oldukları gibi.

Raymond Hettinger var mükemmel bir öğretici ben daha onları açıklayan çok daha iyi bir iş yapar.

152
cevap Nick Johnson 2012-01-18 20:22:21
kaynak

Koşullu Atama

x = 3 if (y == 1) else 2

tam olarak neye benzediğini yapar: "y 1 ise X'e 3 atayın, aksi takdirde X'e 2 atayın". Ebeveynlerin gerekli olmadığını unutmayın, ancak okunabilirlik için onları seviyorum. Daha karmaşık bir şey varsa da zincirleyebilirsiniz:

x = 3 if (y == 1) else 2 if (y == -1) else 1

belli bir noktada olsa da, biraz fazla ileri gidiyor.

eğer kullanabilirsiniz unutmayın ... başka herhangi ifade. Örneğin:

(func1 if y == 1 else func2)(arg1, arg2) 

burada func1, aksi takdirde y 1 ve func2 ise çağrılacaktır. Her iki durumda da karşılık gelen işlev arg1 ve arg2 argümanlarıyla çağrılır.

analog olarak, aşağıdakiler de geçerlidir:

x = (class1 if y == 1 else class2)(arg1, arg2)

burada class1 ve class2 iki sınıf vardır.

142
cevap tghw 2012-01-13 03:37:02
kaynak

Doctest : aynı anda dokümantasyon ve birim testi.

Python belgelerinden çıkarılan örnek:

def factorial(n):
    """Return the factorial of n, an exact integer >= 0.

    If the result is small enough to fit in an int, return an int.
    Else return a long.

    >>> [factorial(n) for n in range(6)]
    [1, 1, 2, 6, 24, 120]
    >>> factorial(-1)
    Traceback (most recent call last):
        ...
    ValueError: n must be >= 0

    Factorials of floats are OK, but the float must be an exact integer:
    """

    import math
    if not n >= 0:
        raise ValueError("n must be >= 0")
    if math.floor(n) != n:
        raise ValueError("n must be exact integer")
    if n+1 == n:  # catch a value like 1e300
        raise OverflowError("n too large")
    result = 1
    factor = 2
    while factor <= n:
        result *= factor
        factor += 1
    return result

def _test():
    import doctest
    doctest.testmod()    

if __name__ == "__main__":
    _test()
141
cevap Pierre-Jean Coudert 2012-01-18 20:18:31
kaynak

adlı biçimlendirme

% - biçimlendirme bir sözlük alır (%ı/%s vb. de geçerlidir. doğrulama.)

>>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}
The answer is 42.

>>> foo, bar = 'question', 123

>>> print "The %(foo)s is %(bar)i." % locals()
The question is 123.

ve yerliler() aynı zamanda bir sözlük olduğundan, bunu bir dict olarak geçirebilir ve yerel değişkenlerinizden % -substitionlara sahip olabilirsiniz. Bence bu kaşlarını çattı, ama bazı şeyleri basitleştiriyor..

Yeni Stil '

>>> print("The {foo} is {bar}".format(foo='answer', bar=42))
138
cevap Pasi Savolainen 2012-01-18 20:20:44
kaynak

daha python modülleri eklemek için (özellikle 3. parti olanlar), çoğu insan PYTHONPATH ortam değişkenlerini kullanıyor gibi görünüyor ya da site paketleri dizinlerinde sembolik bağlar veya dizinler ekliyorlar. Başka bir yol, *kullanmaktır.pth dosyaları. İşte resmi python doc açıklaması:

"en uygun yol [değiştirmek için python'un arama yolu] bir yol eklemektir bir dizine yapılandırma dosyası Bu zaten Python'un yolunda, genellikle .../ site paketleri/ dizin. Yol yapılandırma dosyaları bir uzantısı var.pth ve her satır tek bir yol içermelidir sys eklenecektir.yol. (Çünkü yeni yollar eklenir sys.yol, eklenen modüller dizinler standart geçersiz kılmaz modül. Bu, bunu kullanamayacağınız anlamına gelir sabit yükleme mekanizması standart modüllerin sürümleri.) "

132
cevap dgrant 2008-09-22 12:43:11
kaynak

istisna başka madde:

try:
  put_4000000000_volts_through_it(parrot)
except Voom:
  print "'E's pining!"
else:
  print "This parrot is no more!"
finally:
  end_sketch()

başka yan kullanın yanlışlıkla bunu deneyin tarafından korunan kod tarafından büyütülmemiş bir istisna yakalamak önler, çünkü deneyin maddesi için ek kod ekleyerek daha iyidir ... açıklama hariç.

bkz. http://docs.python.org/tut/node10.html

122
cevap Constantin 2010-09-22 09:55:08
kaynak

re-raising exceptions :

# Python 2 syntax
try:
    some_operation()
except SomeError, e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

# Python 3 syntax
try:
    some_operation()
except SomeError as e:
    if is_fatal(e):
        raise
    handle_nonfatal(e)

bir hata işleyicisi içindeki argümansız 'raise' ifadesi, Python'a istisnasını orijinal geri dönüş ile olarak yeniden yükseltmesini söyler ve " OH, üzgünüm, üzgünüm, bunu yakalamak istemedim, üzgünüm, üzgünüm."

orijinal traceback ile yazdırmak, saklamak veya keman yapmak isterseniz, sys ile alabilirsiniz.exc_ınfo () ve yazdırma Python gibi 'traceback' modülü ile yapılır.

114
cevap Thomas Wouters 2010-04-06 06:08:56
kaynak

ana mesajlar:)

import this
# btw look at this module's source :)

de-cyphered :

Tim Peters tarafından Python Zen

güzel çirkin daha iyidir.

Explicit örtük daha iyidir.

Basit Karmaşık daha iyidir.

Karmaşık karmaşık daha iyidir.

Düz iç içe geçmiş daha iyidir.

Seyrek yoğun daha iyidir.

Okunabilirlik sayılır.

Özel davalar kuralları kıracak kadar özel değildir.

Pratiklik saflığı yense de.

Hatalar asla sessizce geçmemelidir.

Açıkça susturulmadıkça.

Belirsizlik karşısında, tahmin etmek için günaha reddetme. Bir tane olmalı ve tercihen sadece bir tane olmalı. bunu yapmanın açık yolu.

Her ne kadar Hollandalı olmadığınız sürece bu şekilde ilk başta açık olmayabilir.

Şimdi hiç olmadığı kadar iyi.

Her ne kadar şimdi sağ genellikle daha iyidir.

Uygulama açıklamak zorsa, bu kötü bir fikir.

eğer... uygulanması açıklamak kolaydır, iyi bir fikir olabilir.

Ad alanları harika bir fikirdir-bunlardan daha fazlasını yapalım!

106
cevap Mark 2009-10-20 11:08:14
kaynak

Interactive Interpreter Tab '

try:
    import readline
except ImportError:
    print "Unable to load readline module."
else:
    import rlcompleter
    readline.parse_and_bind("tab: complete")


>>> class myclass:
...    def function(self):
...       print "my function"
... 
>>> class_instance = myclass()
>>> class_instance.<TAB>
class_instance.__class__   class_instance.__module__
class_instance.__doc__     class_instance.function
>>> class_instance.f<TAB>unction()

ayrıca bir PYTHONSTARTUP ortam değişkeni ayarlamanız gerekir.

105
cevap mjard 2008-10-03 22:38:15
kaynak

iç içe geçmiş liste kavrayışları ve jeneratör ifadeleri:

[(i,j) for i in range(3) for j in range(i) ]    
((i,j) for i in range(4) for j in range(i) )

bunlar, iç içe geçmiş döngü kodunun büyük parçalarını değiştirebilir.

91
cevap Rafał Dowgird 2008-09-19 16:45:44
kaynak

operatör aşırı yükleme için set yerleşik:

>>> a = set([1,2,3,4])
>>> b = set([3,4,5,6])
>>> a | b # Union
{1, 2, 3, 4, 5, 6}
>>> a & b # Intersection
{3, 4}
>>> a < b # Subset
False
>>> a - b # Difference
{1, 2}
>>> a ^ b # Symmetric Difference
{1, 2, 5, 6}

standart kütüphane referansından daha fazla detay: set türleri

91
cevap Kiv 2012-02-03 22:46:54
kaynak

Diğer sorular python hidden-features