2009-08-20 14 views
9

Obj-C (uzun zamandır kullanmamış olduğum), sınıfları genişletmek için categories adlı bir şeye sahiptir. Bir kategoriyi yeni yöntemlerle açıklamak ve programınıza derlemek, sınıfın tüm örnekleri aniden yeni yöntemlere sahiptir.Obj-C Kategoriler Python'da Nasıl Yapılır?

Python'un kullanabileceğim karıĢım olanakları vardır, ancak karıĢımlar programın altından kullanılmalıdır: sınıfın kendisini bildirmesi gerekir.

Öngörülen kategori kullanım durumu: Verilerle etkileşimde bulunmanın farklı yollarını açıklayan ve farklı özelliklere ulaşmak için polimorfik yollar açıklayan büyük bir sınıf hiyerarşiniz olduğunu varsayalım. Artık bir kategori, bu yöntemleri tek bir yerde kullanmak için uygun bir arayüz uygulayarak bu tanımlayıcı sınıfların tüketicisine yardımcı olabilir. (Bir kategori yöntemi, örneğin, iki farklı yöntemi deneyebilir ve ilk tanımlı (Non-None) dönüş değerini döndürür.)

Bunu Python'da yapmanın herhangi bir yolu var mı?

Örnek kod

Ben

umut bu ne demek istediğimi açıklık getirmektedir. Buradaki nokta, Kategorinin bir toplu arayüz olması, AppObj tüketicisinin kodunun kodunu değiştirebilmesidir.

class AppObj (object): 
    """This is the top of a big hierarchy of subclasses that describe different data""" 
    def get_resource_name(self): 
    pass 
    def get_resource_location(self): 
    pass 

# dreaming up class decorator syntax 
@category(AppObj) 
class AppObjCategory (object): 
    """this is a category on AppObj, not a subclass""" 
    def get_resource(self): 
    name = self.get_resource_name() 
    if name: 
     return library.load_resource_name(name) 
    else: 
     return library.load_resource(self.get_resource_location()) 
+0

, sen AppObj veya AppObjCategory örneğini ki? BTW Python, şu anda 2.6'da sınıf dekoratörlerine sahiptir: http://docs.python.org/whatsnew/2.6.html#pep-3129-class-decorators –

+0

AppObj'yi (ve alt sınıflarını) örnekliyorum. Kategori kodu tamamen ayrı olabilir (yani AppObj bir kütüphanede, uygulamada Kategori olabilir). – u0b34a0f6ae

+0

Belki de o zaman hemen Kategori sınıf dekoratörünü uygulamak için bir durum; Kategorideki tüm öznitelikleri temel sınıfa kopyalayın, .. __doc__ ve __dict__? gibi bazı öznitelikleri atlayın. – u0b34a0f6ae

cevap

2

Bir sınıf dekoratörünün bu uygulamayla geldim. Ben python2.5 kullanıyorum bu yüzden aslında dekoratör sözdizimi (güzel olurdu) ile test etmedim, ve gerçekten ne yaptığını emin değilim. Ama şuna benzer:

""" 
This module implements Obj-C-style categories for classes for Python 

Copyright 2009 Ulrik Sverdrup <[email protected]> 
License: Public domain 
""" 

def Category(toclass, clobber=False): 
    """Return a class decorator that implements the decorated class' 
    methods as a Category on the class @toclass 

    if @clobber is not allowed, AttributeError will be raised when 
    the decorated class already contains the same attribute. 
    """ 
    def decorator(cls): 
     skip = set(("__dict__", "__module__", "__weakref__", "__doc__")) 
     for attr in cls.__dict__: 
      if attr in toclass.__dict__: 
       if attr in skip: 
        continue 
       if not clobber: 
        raise AttributeError("Category cannot override %s" % attr) 
      setattr(toclass, attr, cls.__dict__[attr]) 
     return cls 
    return decorator 
8

Neden yöntemler dinamik olarak eklemiyorsunuz?

>>> class Foo(object): 
>>>  pass 
>>> def newmethod(instance): 
>>>  print 'Called:', instance 
... 
>>> Foo.newmethod = newmethod 
>>> f = Foo() 
>>> f.newmethod() 
Called: <__main__.Foo object at 0xb7c54e0c> 

Objective-C'yi biliyorum ve bu sadece kategoriler gibi görünüyor. Tek dezavantajı, bunu yerleşik veya uzantı türlerine yapamazsınız.

+1

tek fark, kategorinin daha sistematik veya açık olmasıdır, özellikle de kavramı zaten biliyorsanız. – u0b34a0f6ae

+0

Bu küçük ilgili yardımın bir kısmını eklemek istiyorum: bu nesnenin '__class __.__ mro__' kullanarak bir nesnenin üst sınıflarını alabilirsiniz. Bu yöntemi eklemek ve ortak sınıflarını aramak istediğiniz birden fazla sınıfa sahipseniz, bu yararlı olabilir. – ArtOfWarfare

2

Python'un setattr işlevi bu kolaylaştırır

pycategories.py. Örnekte

# categories.py 

class category(object): 
    def __init__(self, mainModule, override = True): 
     self.mainModule = mainModule 
     self.override = override 

    def __call__(self, function): 
     if self.override or function.__name__ not in dir(self.mainModule): 
      setattr(self.mainModule, function.__name__, function) 

 

# categories_test.py 

import this 
from categories import category 

@category(this) 
def all(): 
    print "all things are this" 

this.all() 
>>> all things are this 
İlgili konular