8

Farklı işlevlerin, yalnızca oturum açmış kullanıcının gerekli izin düzeyine sahip olması durumunda yürütülebilir olmasını istiyorum.dekoratör işlevinin niteliklerini ayarlamak için

Hayatımı daha karmaşık hale getirmek için dekoratörler kullanmak istiyorum. Aşağıda, aşağıda gösterildiği gibi 'dekore edilmiş' işlevler üzerinde permission özniteliğini ayarlamak için dikkatle çalışıyorum.

def permission(permission_required): 
    def wrapper(func): 
     def inner(*args, **kwargs): 
      setattr(func, 'permission_required', permission_required) 
      return func(*args, **kwargs) 
     return inner 
    return wrapper 

@permission('user') 
def do_x(arg1, arg2): 

    ... 

@permission('admin') 
def do_y(arg1, arg2): 
    ... 

Ama ne zaman:

fn = do_x 
if logged_in_user.access_level == fn.permission_required: 
    ... 

bir hata 'function' object has no attribute 'permission_required'

ben eksik olsun?

+1

: sana [ 'functools.wraps'] (http://docs.python.org/2/library/functools.html#functools.wraps kullanmak istiyorum eminim) İşte. Sorununuzu doğrudan çözmemek için değil, ancak her işlev "iç", "(args, ** kwargs)" ifadesini aldığında, bu tür kodu hata ayıklamak imkansız olduğu için, 'yanlış kaynağa teftiş' – abarnert

cevap

14

Özniteliği iç (sarmalayıcı) işlevinde ayarlıyorsunuz. Hepiniz bir sarıcı işlev gerekmez:

def permission(permission_required): 
    def decorator(func): 
     func.permission_required = permission_required 
     return func 
    return decorator 

Kişisel dekoratör orijinal fonksiyonunu değiştiririzşey dönmek gerekiyor. Özgün işlevin kendisi (özellik eklendiğinde) bunun için iyi olacaktır, çünkü tüm yapmak istediğiniz bir özellik eklemektir.

hala sarmalayıcı gerekiyorsa, o zaman bunun yerine sarıcı işlevi üzerine niteliğini ayarlayın: o yüzden Sonuçta

def permission(permission_required): 
    def decorator(func): 
     def wrapper(*args, **kwargs): 
      # only use a wrapper if you need extra code to be run here 
      return func(*args, **kwargs) 
     wrapper.permission_required = permission_required 
     return wrapper 
    return decorator 

, sen dekoratör tarafından döndürülen sargı ile sarılmış işlevi değiştiriyorsanız nesne üzerinde özellik arıyor olacaksınız.

+0

Dekore edilmiş fonksiyonda argümanlara izin vermek için sarıcıya ihtiyacım var. Kodunuzu kullandım ve harika çalıştı - ancak argüman için sarıcı eklediğimde hata geri geldi. – rikAtee

+1

@rikAtee: Dekore edilmiş işlevde argümanlara izin vermek için sarıcıya ihtiyacınız yoktur. İlk örnek sadece işlevi değiştirir ve döndürür; hala dekore edilmeden önce yaptığı aynı argümanları alır. – abarnert

+0

@rikAtee: Yaptığınız tek şey özniteliği ayarlamaksa, sarmalayıcı * * * gereklidir. Sadece bir sarıcıya ihtiyaç varsa bir sarıcı ekleyin (örn. Argümanlar veya dönüş değerleri üzerinde çalışmak için ekstra kod ekler veya işlev çağrıldığında ekstra şeyler yapar). –

1

do_x veya do_y, do_x veya do_y yürütülmesi sonuç döndürmez yerini alabilir bir işlev dönmelidir Kişisel dekoratör Sen olarak aşağıda süslemek modity edebilirsiniz: Elbette

def permission(permission_required): 
    def wrapper(func): 
     def inner(): 
      setattr(func, 'permission_required', permission_required) 
      return func 
     return inner() 
    return wrapper 

, başka kısa çözümü var : bir yan not olarak

def permission(permission_required): 
    def wrapper(func): 
     setattr(func, 'permission_required', permission_required) 
     return func 
    return wrapper 
+1

İçsel işleviniz * hiçbir şey *, bu yüzden orijinali, sarılmış işlevde bir öznitelikten daha fazla bir şey yapmayan bir işlevle değiştiriyorsunuz, bu da * işe yaramaz *. –

İlgili konular