获取描述符对象的简洁方法 [英] Neat way to get descriptor object

查看:103
本文介绍了获取描述符对象的简洁方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Python 3中

class A(object):
    attr = SomeDescriptor()
    ...
    def somewhere(self):
        # need to check is type of self.attr is SomeDescriptor()
        desc = self.__class__.__dict__[attr_name]
        return isinstance(desc, SomeDescriptor)

有更好的方法吗?我不喜欢这个self.__class__.__dict__东西

Is there better way to do it? I don't like this self.__class__.__dict__ stuff

推荐答案

A.attr导致Python调用SomeDescriptor().__get__(None, A),因此如果SomeDescriptor.__get__instNone时返回self,则将返回描述符:

A.attr causes Python to call SomeDescriptor().__get__(None, A) so if you have SomeDescriptor.__get__ return self when inst is None, then A.attr will return the descriptor:

class SomeDescriptor():
    def __get__(self, inst, instcls):
        if inst is None:
            # instance attribute accessed on class, return self
            return self

然后您使用来访问描述符

Then you access the descriptor with

desc  = type(self).attr

如果仅将属性名称称为字符串attr_name,则可以使用

If the attribute's name is known only as a string, attr_name, then you would use

desc  = getattr(type(self), attr_name)

即使selfA子类的实例,该功能仍然有效,而

This works even if self is a instance of a subclass of A, whereas

desc = self.__class__.__dict__[attr_name]

仅在selfA的实例时起作用.

would only work if self is an instance of A.

class SomeDescriptor():
    def __get__(self, inst, instcls):
        if inst is None:
            # instance attribute accessed on class, return self
            return self
        return 4

class A():
    attr = SomeDescriptor()
    def somewhere(self):
        attr_name = 'attr'
        desc  = getattr(type(self), attr_name)
        # desc = self.__class__.__dict__[attr_name]  # b.somewhere() would raise KeyError
        return isinstance(desc, SomeDescriptor)

这显示A.attr返回描述符,并且a.somewhere()正常工作:

This shows A.attr returns the descriptor, and a.somewhere() works as expected:

a = A()
print(A.attr)
# <__main__.SomeDescriptor object at 0xb7395fcc>    
print(a.attr)
# 4    
print(a.somewhere())
# True

这表明它也适用于A的子类.如果您不加评论 desc = self.__class__.__dict__[attr_name],您会看到 b.somewhere()引发KeyError:

This shows it works for subclasses of A too. If you uncomment desc = self.__class__.__dict__[attr_name], you'll see b.somewhere() raises a KeyError:

class B(A): pass
b = B()
print(B.attr)
# <__main__.SomeDescriptor object at 0xb7395fcc>   
print(b.attr)
# 4    
print(b.somewhere())
# True


顺便说一句,即使您不能完全控制SomeDescriptor的定义,您仍然可以将其包装在一个描述符中,当inst为None时,该描述符返回self:


By the way, even if you do not have full control over the definition of SomeDescriptor, you can still wrap it in a descriptor which returns self when inst is None:

def wrapper(Desc):
    class Wrapper(Desc):
        def __get__(self, inst, instcls):
            if inst is None: return self
            return super().__get__(inst, instcls)
    return Wrapper

class A():
    attr = wrapper(SomeDescriptor)()
    def somewhere(self):
        desc  = type(self).attr
        # desc = self.__class__.__dict__[attr_name]  # b.somewhere() would raise KeyError
        return isinstance(desc, SomeDescriptor)

因此无需使用

desc = self.__class__.__dict__[attr_name]

desc = vars(type(self))['attr']

也遇到同样的问题.

这篇关于获取描述符对象的简洁方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆