代码之家  ›  专栏  ›  技术社区  ›  u0b34a0f6ae

如何在Python中创建Obj-C类别?

  •  9
  • u0b34a0f6ae  · 技术社区  · 15 年前

    Obj-C(我很久没有用过)有一个叫做 categories 扩展课程。用新方法声明一个类别并将其编译到程序中,该类的所有实例突然都有了新方法。

    Python有mixin的可能性,我使用它,但是mixin必须从程序的底部使用:类必须声明它自己。

    可预见的类别用例:假设您有一个描述与数据交互的不同方式的大类层次结构,声明获取不同属性的多态方式。现在,一个类别可以通过实现一个方便的接口在一个地方访问这些方法来帮助这些描述类的使用者。(例如,category方法可以尝试两种不同的方法并返回第一个定义的(非None)返回值。)

    说明性代码

    希望 这澄清了我的意思。关键是,类别就像一个聚合接口,AppObj的消费者可以在其中更改 它的

    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())
    
    3 回复  |  直到 15 年前
        1
  •  9
  •   fraca7    15 年前

    为什么不动态添加方法呢?

    >>> 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,这看起来就像类别。唯一的缺点是无法对内置类型或扩展类型执行此操作。

        2
  •  4
  •   u0b34a0f6ae    15 年前

    我提出了这个类装饰器的实现。我使用的是python2.5,所以我还没有用decorator语法对它进行测试(这很好),我不确定它的功能是否正确。但看起来是这样的:

    pycategories.py

    """
    This module implements Obj-C-style categories for classes for Python
    
    Copyright 2009 Ulrik Sverdrup <ulrik.sverdrup@gmail.com>
    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
    
        3
  •  2
  •   Patrick Perini    11 年前

    setattr

    # 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