7

Farz edelim Önceden belirlenmiş belirli aralıklarda rastgele seçilmiş değerlere sahip 4-tuple döndüren generator isimli bir işlev var. Diyelim ki böyle tanımlarla 20 farklı işlevleri tanımladıktan diyelim Öte yandanPython'daki işlev parametrelerini eşleştirme

age is in range(5, 85) 
sex is a member of the set {"m", "f"} 
location is a member of the set of all the cities in California 
marital_status is a member of {"married", "single", "separated"} 

: en tanımlama grubu formunda (age, sex, location, marital_status) ait diyelim p1 parametreleri alması gerekirken

def p1 (age, sex, location, marital_status) 
def p2 (age, sex, location, marital_status) 
. 
. 

aşağıdaki formu değerleri: tüm yol 0 p2 için

`age` must be in the range 20 to 45 
`sex` must be male 
`location` could be any city in Southern California 
`marital_status` could be either single or married 

ve değerlerin farklı bir dizi hayal.

Oluşturulan hangi değerler kümesinin hangi işlevle eşleştiğini belirlemenin pragmatik bir yolu nedir?

tüm tanımları tam olarak aynı Bu durumda

ama age ve location olanakları aralığında belirli sınırlamalarla birlikte def p1 (age, location) olabilir örneğin p18 için tanımlarında ufak farklar olabilir örneklerini tahmin edebilirsiniz.

P.S. Patterler mutlaka karşılıklı olarak münhasır değildir, yani bir dizi üretilen değer, aynı zamanda birden fazla fonksiyonla eşleşebilir.

+0

Eğer Python 3 olduğundan, * Fonksiyon ek açıklamalar * gitmek için bir yol olabilir. – cdarke

+0

Kalıplar birbirini dışlıyor mu yoksa daha fazla desen eşleşmesi mümkün mü? – dlask

+0

@dlask: İyi nokta. Modelin birden fazla fonksiyonla eşleşmesi küçük bir olasılıktır. –

cevap

1

(ancak 2.X değil), bir işlev nesnesine annotation information (bir işlevin argümanları ve sonucu hakkında isteğe bağlı kullanıcı tanımlı veriler) ekleyebilirsiniz. Burada argümanlarınızın aralığını kontrol etmek için işlevinizi sarmalamak için bu özelliği bir dekoratörde kullanabilirsiniz.

Örneğin şu aralık testi işlevini kullanabilirsiniz:

def rangetest(func): 
    def onCall(**kargs): 
     argchecks = func.__annotations__ 

     if all(val in range(*argchecks.get(arg)) for arg,val in kargs.items()): 
      return func(**kargs) 
     else : 
       print ("invalid arg range") 
    return onCall 


@rangetest 
def func(a:(1, 5), b:(4,7), c:(0, 10)): 
    print(a + b + c) 

Demo:

func(a=2, b=6, c=8) 
16 
func(a=2, b=6, c=8) 
invalid arg range 

Burada bazı anlamı yoktur.Birincisi, ek açıklama bilgisi bir sözlük içerisindeyse (python bunu sözlük olarak döndürür) ve sözlüklerin belirli bir sırasına sahip olmadığından, ek açıklamada göreceli aralığını elde etmek için fonksiyonunuzda anahtar kelime argümanlarını kullanmanız gerekir. bilgi sözlüğü.

Ayrıca burada sayısal aralığı kullandım, ancak sorgunuzda gösterdiğiniz gibi sözcüklerin listesi gibi bazı özel aralıkları kullanabilirsiniz. Ancak, türünü temel alarak, türüne göre doğru bir işlem kullanmanız gerekir: all https://www.python.org/dev/peps/pep-3107/:

all(kwargs.get(arg) in range(*arg_range) if is instance (arg_range,tuple) else kwargs.get(arg) in arg_range for arg,arg_range in argchecks.items()) 
1
# define test t1 for function p1 
def t1(params): 
    return params["age"] in range(5, 85) \ 
     and params["sex"] in ["m", "f"] \ 
     and cityof(params["location"], "California") \ 
     and params["marital_status"] in ["married", "single", "separated"] 
# and similarly for other p* functions 

# define functions 
def p1(params): ... 
def p2(params): ... 
# and so on 

# bind tests and functions 
RULES = { 
    (t1, p1), 
    (t2, p2), 
    ... 
} 

# have the right functions called 
def go(params): 
    for rule in RULES: 
     if rule[0](params): 
      rule[1](params) 

# test it 
go({"age": 6, "sex": "m", "location": "somewhere", "marital_status": "single"}) 

Sadece birkaç yorum:

  • testler fonksiyonları kendileri dahil edilebilir.
  • Test fonksiyonları, eksik parametrelerle de baş etmek zorunda.
  • Ayrıca, işlev parametrelerini doğrudan kullanmak da mümkündür.

çeşitli varyasyonları gerçekten mümkün bulunmaktadır ama ana prensip aynıdır:
eşleştirme işlevini bulun ve diyoruz.

1

(yerine türü her argüman kontrol etme) Fonksiyonlarınızdan biçimlendirilmiş doc dizeleri eklemek isteyen varsa, o zaman böyle bir şey yaptığını düşünebiliriz: Python 3.X bir Pythonictir yol olarak

# This function has a foratted doc string. 
# :argument: Truth condition to be evaluated 
# If any condition is False, function won't be called 
def party_list(name, age, sex): 
    """ 
    :name:"{}" != "Dad" 
    :age:17< {} <25 
    :sex:True 
    """ 
    print("You're invited to my party, {}!".format(name)) 


# We will make some sample data 
keys = ["name", "age", "sex"] 
values = [["John", 24, "Male"], 
      ["Sarah", 25, "Female"], 
      ["Pikachu", 2, "Pokemon"], 
      ["Pizza guy", 18, "Male"]] 
# Turn it in to a dictionary 
for key, value in enumerate(values): 
    values[key] = {t:p for t, p in zip(keys, value)} 


# These conditions can be dynamically made for each function, 
# because we have access to the doc string from the outside 
conditions = list(filter(lambda c: ':' in c, party_list.__doc__.split('\n'))) 
for friend in values: 
    for case in conditions: 
     tag, code = case.split(':')[1:] 
     if not eval(code.format(friend[tag])): 
      break 
    else: 
     party_list(friend["name"], friend["age"], friend["sex"])