在Python

时间:2016-06-19 21:54:25

标签: python metaprogramming descriptor

以下是Python中descriptor用法的一个简单示例:

class MyDescriptor(object):
  def __get__(self, obj, objtype):
    return 42

class MyClass(object):
  d = MyDescriptor()

print MyClass().d  # 42

但是,如果我希望描述符对象成为类的实际属性,那么MyClass().d将是MyDescriptor实例,而不是42。

3 个答案:

答案 0 :(得分:1)

有很多方法可以获得你想要的东西,具体取决于你想要的东西。

如果您只想访问描述符对象(即,您不关心它是否实际上直接存储为类的属性),那么只需将其存储在列表或其他内容中:

class Foo(object):
    descriptor = [MyDescriptor()]

这需要额外的间接级别来访问它,但在实践中,这可能比替代方案更少。

the documentation中所述,描述符通过object.__getattribute__激活。因此,如果您真的希望它是一个属性,您可以在包含描述符(__getattribute__)的类上覆盖MyClass,从而阻止描述符机制生效:

class MyClass(object):
  d = MyDescriptor()

  def __getattribute__(self, attr):
    if attr=='d':
        return self.__class__.__dict__['d']
    else:
        return super(MyClass, self).__getattribute__(attr)

>>> MyClass().d
<__main__.MyDescriptor object at 0x0000000002843E80>

答案 1 :(得分:1)

使用inspect.getattr_static

  

getattr_static()无法解析描述符,例如slot   在C中实现的对象上的描述符或getset描述符   返回描述符对象的基础属性。

>>> import inspect
>>> inspect.getattr_static(MyClass, 'd')
<__main__.MyDescriptor object at 0x105678c18>
>>> inspect.getattr_static(MyClass(),"d")
<__main__.MyDescriptor object at 0x105678c18>

如果您希望将此设置为实例的默认行为,则可以将__getattribute__覆盖为getattr_static

class MyClass(object):
  from inspect import getattr_static as __getattribute__
  d = MyDescriptor()

>>> MyClass().d
<__main__.MyDescriptor object at 0x105678c18>

坦率地说,我不明白为什么你会想要这个,将描述符存储在一个不会调用像dict这样的描述符的数据结构中会更有意义:

descriptors = {"d": MyDescriptor()}

然后你可以查找descriptors["d"]而不会有调用描述符的风险。

答案 2 :(得分:0)

我最简单的想法是将这个描述符包装成另一个描述符。它可以工作,因为只会调用一个try { String path = "upload/1.jpg"; Path p = Paths.get(path); InputStream is = new FileInputStream(p.toFile()); res.raw().setContentType(Files.probeContentType(p)); res.raw().setHeader("Content-Disposition", "inline; filename=" + p.getFileName()); byte[] buffer = new byte[1024]; int len; while ((len = is.read(buffer)) > 0) { res.raw().getOutputStream().write(buffer, 0, len); } String result = IOUtils.toString(is); is.close(); return result.trim(); } catch (Exception e) { // handle the exceptions the way you want logger.error("Error while getting resource", e); res.status(500); return ""; }

__get__