2010-10-15 10 views
7

Python işlevlerini bildirmek ve bunları daha sonra veya ayrı bir dosyada tanımlamak mümkün mü?Python'da okunabilir ve temiz bir kod olması için işlev bildirimi?

class tata: 
    def method1(self): 
     def func1(): 
     # This local function will be only used in method1, so there is no use to 
     # define it outside. 
     # Some code for func1. 
     # Some code for method1. 

sorun kodu dağınık ve okunması zor hale gelmesidir:

Bazı kod gibi var. Bu yüzden func1method1 içinde bildirmek ve daha sonra tanımlamak mümkün olup olmadığını merak ediyorum?

+0

Eğer func1() yöntemi gerçekten sadece method1() ile ilgiliyse ve içsel yöntem sizin için bir sorunsa, bunun gerçekten ayrı bir sınıf olması gerektiğinin bir göstergesidir. –

cevap

6

Tabii, sorun:

foo.py:

def func1(): 
    pass 

script.py:

import foo 
class tata: 
    def method1(self): 
     func1=foo.func1 
+0

Güzel düşünce! Bununla birlikte, yerel bir işlev düşüncesi, bu işlevi sadece iç alan içerisinde kullanılabilir kılmaktır. Yani, 'method1' içinde yeni' func1' tanımlamak amacı nedir? Bunu yapmak daha kolay olmazdı: foo import func1'den foo kullan ve kullan. – banx

+0

@banx: Alex Martelli'nin cevabı burada (http: // stackoverflow.com/questions/1744258/is-import-module-daha iyi-kodlama-style-than-from-module-import-function) 'foo import func1'den tamamen kaçınmak için beni ikna etti. – unutbu

+0

@banx: Evet, 'fun1 'ifadesini' method1' içinde koymak, onu en azından yarı-özel yapar, ama ben onu bir mütevazi bayt kodu korsanının önüne koyamazdım (http://stackoverflow.com/questions/3908335/python -özel-özel-ad-bir-dış-kapsam-3913185 # 3913185) özel değil-özel olduğunu düşündüğümüzü yapmak için bir yol bulmak için. – unutbu

2

İç tanım, iç alanda ayrı bir ad oluşturur. Daha sonra aynı adla tanımladığınız her şeyi gölgeleyecektir. Daha sonra işlevi tanımlamak isterseniz, bunu yapın. İsim sadece kullanıldığı zaman için kontrol edilecektir.

def foo(): 
    print 'foo' 
    bar() 

def bar(): 
    print 'bar' 

foo() 
3

Ben ne istediğini method1 içinde işlevini ithal etmek olduğunu düşünüyorum , Örneğin

def method1(...): 
    from module_where_func1_is_defined import func1 
    # do stuff 
    something = func1(stuff, more_stuff) 
    # do more stuff 

Python modülleri temel olarak yalnızca dosyalardır; module_where_func1_is_defined.py dosyası, komut dosyanızla aynı dizinde bulunduğunda, method1 bunu içe aktarabilir. (

import other_module 

# various codes 

def method1(other_args, func=other_module.func1) 
    # do stuff 
    something = func(stuff, more_stuff) 
    # do more stuff 
2

func1 ise: İşlem method1 eser özelleştirmek ve aynı zamanda daha da net o func1 kullandığı yapabilmek istiyorsanız

, varsayılan bir parametre olarak method1 için func1 geçebilir) method1() kapsamındaki herhangi bir şeyi işlemek gerekiyor. Func1() 'un tanımını burada bırakıyorsunuz. Sen buna anonim olması mümkün değildir Ancak sonradan

 

class Something(object): 
    def test1(self): 
    pass 

def dummy(self): 
    print "ok", self 

Something.test1 = dummy 

yöntemleri oluşturabilir

+0

+1 Yuvalanmış işlevlerin sahip oldukları kapsamlardan doğrudan erişebilmeleri, Python'da önemli bir deyimdir. Mevcut kapsam kuralları çok güçlü ve iyi düşünülmüş durumda - bkz. Python 2.1'de tanıtılan [PEP 227 - Statik İç içe Kapsamlı Kapsamlar (ttp: //www.python.org/dev/peps/pep-0227/). Tanımları ayrı bir dosyaya koymak, bir şekilde işlenmediği sürece şu anda bunu önleyecektir. – martineau

0

Method1 kapsamı() içinde tanımlanmış değilse parametre olarak herhangi bir ilgili veri almak) (FUNC1 olması gerekecek fonksiyonu (kuyu, orada lambda ifadelerdir ama orada ifadeleri olamaz), sen bunu daha okunabilir hale getirmek için dekoratörler kullanmak isteyebilirsiniz

geçici Adını sağlamak zorunda:

 
def define(cls, name): 
    def decor(f): 
    setattr(cls, name, f) 
    return decor 


class Something(object): 
    def test1(self): 
    pass 

@define(Something, "test1") 
def dummy(self): 
    print "ok", self 

Bu kod daha okunabilir olmalıdır. Hala mankenleri kirletecek ama null ile başlatacak.