Python fonksiyon tanımlarında -> ne anlama geliyor?


476

Son zamanlarda Python 3.3 dilbilgisi spesifikasyonuna bakarken ilginç bir şey fark ettim :

funcdef: 'def' NAME parameters ['->' test] ':' suite

İsteğe bağlı 'ok' bloğu Python 2'de yoktu ve Python 3'teki anlamı hakkında herhangi bir bilgi bulamadım. Bu doğru Python ve yorumlayıcı tarafından kabul edildi:

def f(x) -> 123:
    return x

Bunun bir tür önkoşul sözdizimi olabileceğini düşündüm, ama:

  • xBurada test yapamıyorum , hala tanımsız,
  • Oktan sonra ne koyarsam yapayım (örneğin 2 < 1), işlev davranışını etkilemez.

Bu sözdizimine alışkın olan herkes açıklayabilir mi?

Yanıtlar:


375

Bu bir işlev notudur .

Daha ayrıntılı olarak, Python 2.x, çeşitli nesne türlerine bir meta veri dizesi eklemenizi sağlayan docstring'lere sahiptir. Bu inanılmaz derecede kullanışlıdır, bu nedenle Python 3, parametrelerini ve dönüş değerlerini tanımlayan işlevlere meta veriler eklemenizi sağlayarak özelliği genişletir.

Önceden tasarlanmış bir kullanım durumu yoktur, ancak PEP birkaç tane önerir. Çok kullanışlı olanı, parametrelere beklenen türleriyle açıklama eklemenizi sağlamaktır; ek açıklamaları doğrulayan veya bağımsız değişkenleri doğru türe zorlayan bir dekoratör yazmak daha kolay olacaktır. Bir diğeri, dokümana kodlamak yerine parametreye özgü belgelere izin vermektir.


122
Ve bilgi bir .__annotations__özellik olarak mevcuttur .
Martijn Pieters

8
Vay canına, oldukça geniş bir bilgi alanını kaçırdım - sadece değer ek açıklamaları değil, aynı zamanda parametre ek açıklamaları da. Çok teşekkür ederim :).
Krotton

4
@Krotton Seni özlediğin için suçlayamam, pratik olarak kullanılmadı. Bunları kullanarak sadece tek bir kütüphaneyle tanıştım ve bu oldukça belirsiz.

5
Ve __annotations__öznitelik bir sözlüktür. Anahtar return, oktan sonraki değeri almak için kullanılan anahtardır .
Keith

9
@delnan - muhtemelen çoğunlukla kullanılmamasının nedeni, çoğu python kütüphanesinin hala python2.x ile uyumlu olmayı amaçlamasıdır.
Python3.x

252

Bunlar PEP 3107'de yer alan fonksiyon açıklamalarıdır . Özellikle, ->dönüş işlevi ek açıklamasını işaretler.

Örnekler:

>>> def kinetic_energy(m:'in KG', v:'in M/S')->'Joules': 
...    return 1/2*m*v**2
... 
>>> kinetic_energy.__annotations__
{'return': 'Joules', 'v': 'in M/S', 'm': 'in KG'}

Ek açıklamalar sözlüktür, bu nedenle şunları yapabilirsiniz:

>>> '{:,} {}'.format(kinetic_energy(20,3000),
      kinetic_energy.__annotations__['return'])
'90,000,000.0 Joules'

Ayrıca yalnızca bir dize yerine bir python veri yapınız olabilir:

>>> rd={'type':float,'units':'Joules','docstring':'Given mass and velocity returns kinetic energy in Joules'}
>>> def f()->rd:
...    pass
>>> f.__annotations__['return']['type']
<class 'float'>
>>> f.__annotations__['return']['units']
'Joules'
>>> f.__annotations__['return']['docstring']
'Given mass and velocity returns kinetic energy in Joules'

Veya, çağrılan değerleri doğrulamak için işlev niteliklerini kullanabilirsiniz:

def validate(func, locals):
    for var, test in func.__annotations__.items():
        value = locals[var]
        try: 
            pr=test.__name__+': '+test.__docstring__
        except AttributeError:
            pr=test.__name__   
        msg = '{}=={}; Test: {}'.format(var, value, pr)
        assert test(value), msg

def between(lo, hi):
    def _between(x):
            return lo <= x <= hi
    _between.__docstring__='must be between {} and {}'.format(lo,hi)       
    return _between

def f(x: between(3,10), y:lambda _y: isinstance(_y,int)):
    validate(f, locals())
    print(x,y)

Baskılar

>>> f(2,2) 
AssertionError: x==2; Test: _between: must be between 3 and 10
>>> f(3,2.1)
AssertionError: y==2.1; Test: <lambda>

86

Diğer cevapların belirttiği gibi, ->sembol fonksiyon ek açıklamalarının bir parçası olarak kullanılır. Python'un daha yeni sürümlerinde >= 3.5, bunun tanımlanmış bir anlamı vardır.

PEP 3107 - İşlev Açıklamaları , spesifikasyonu, dilbilgisi değişikliklerini, func.__annotations__saklandıkları varlığı ve kullanım durumunun hala açık olduğunu tanımlayarak açıkladı .

Python 3.5olsa - PEP 484 tipi İpuçları buna tek bir anlam vermektedir: ->türü olduğunu işlevin döndürdüğü belirtmek için kullanılır. Ayrıca , ek açıklamaların mevcut kullanımları hakkında ne açıklandığı gibi gelecekteki sürümlerde de uygulanacak gibi görünüyor :

En hızlı düşünülebilen şema, 3.6'da tip ipucu olmayan ek açıklamaların sessizce kullanılmamasını, 3.7'de tam kullanımdan kaldırılmasını ve Python 3.8'de ek açıklamaların izin verilen tek kullanımı olarak tip ipuçlarını beyan edecektir.

(Vurgu madeni)

Bu, 3.6gelecekteki sürümlere çarpılabilmesi için söyleyebildiğim kadarıyla uygulanmadı .

Buna göre, sağladığınız örnek:

def f(x) -> 123:
    return x

gelecekte yasaklanacaktır (ve mevcut sürümlerde kafa karıştırıcı olacaktır), şu şekilde değiştirilmesi gerekir:

def f(x) -> int:
    return x

bu fonksiyonun etkili bir şekilde tanımlanması için fbir tür nesne döndürür int.

Ek açıklamalar Python'un kendisi tarafından hiçbir şekilde kullanılmaz, hemen hemen doldurur ve yok sayar. Onlarla çalışmak üçüncü taraf kütüphanelere kalmış.


64

Aşağıdaki kodda:

def f(x) -> int:
    return int(x)

-> intSadece söyler f()bir tamsayı döndürür (ancak bir tamsayı dönmek için işlev zorlamak değildir). Buna iade notu denir ve olarak erişilebilir f.__annotations__['return'].

Python ayrıca parametre ek açıklamalarını da destekler:

def f(x: float) -> int:
    return int(x)

: floatprogramı okuyan insanlara (ve bazı üçüncü taraf kütüphaneleri / programları, örneğin pylint) xa float. Ona erişilir f.__annotations__['x']ve tek başına bir anlamı yoktur. Daha fazla bilgi için belgelere bakın:

https://docs.python.org/3/reference/compound_stmts.html#function-definitions https://www.python.org/dev/peps/pep-3107/


4

Bu, işlevin döndürdüğü sonuç türü anlamına gelir, ancak olabilir None.

Python 3.x tabanlı modern kütüphanelerde yaygındır.

Örneğin, birçok yerde kütüphane panda profilleme kodu vardır, örneğin:

def get_description(self) -> dict:

def get_rejected_variables(self, threshold: float = 0.9) -> list:

def to_file(self, output_file: Path or str, silent: bool = True) -> None:
"""Write the report to a file.

"Bu, işlevin döndürdüğü sonuç türü anlamına gelir, ancak Yok olabilir." Hiçbiri veya başka bir tür olabilir.
Ebram Shehata

2

def function(arg)->123:

Basitçe bir dönüş türüdür, bu durumda tamsayı hangi sayıyı yazdığınızın önemi yoktur.

Java gibi :

public int function(int args){...}

Ama Python için ( Jim Fasarakis Hilliard nasıl dedi) dönüş türü sadece bir ipucu , bu yüzden dönüş önermek ama yine de bir dize gibi diğer türü döndürmek için izin ver ..


1
def f(x) -> 123:
    return x

Özetim:

  1. Basitçe ->isteğe fonksiyonun dönüş türü belirtmek için geliştiriciler almak için tanıtıldı. Bkz. Python Geliştirme Önerisi 3107

  2. Bu, Python'un kapsamlı bir şekilde benimsenmesi nedeniyle gelecekte nasıl gelişebileceğinin bir göstergesidir - güçlü yazmaya yönelik bir gösterge - bu benim kişisel gözlemim.

  3. Bağımsız değişkenler için de türler belirleyebilirsiniz. İşlevlerin ve bağımsız değişkenlerin dönüş türünün belirtilmesi, mantıksal hataların azaltılmasına ve kod geliştirmelerinin geliştirilmesine yardımcı olacaktır.

  4. İade türü olarak ifadelere sahip olabilirsiniz (hem işlev hem de parametre düzeyinde) ve ifadelerin sonucuna ek açıklama nesnesinin 'return' özelliği üzerinden erişilebilir . ek açıklamalar lambda satır içi işlevlerinin ifade / dönüş değeri için boş olacaktır.


Düzeltmeler için teşekkürler.
maz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.