Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用于字典转换的特殊方法名的内置函数_Python_Python 3.x_Function_Class_Oop - Fatal编程技术网

Python 用于字典转换的特殊方法名的内置函数

Python 用于字典转换的特殊方法名的内置函数,python,python-3.x,function,class,oop,Python,Python 3.x,Function,Class,Oop,我一直在深入研究Python类中的运算符重载和特殊方法,我注意到许多内置函数都有其等效的特殊方法名称: int(x)调用x.\uuuu int\uuuu() next(x)调用Python2中的x.\uuuu next\uuuu()或x.next() 但是,一对函数,即tuple()和dict(),没有任何等效函数。我知道还没有必要使用这种特殊方法,但在某些情况下,对类调用的dict()转换方法可能很有用。我该如何实现这一点?或者,对于试图使用这种逻辑的人,你会怎么评论 # I think

我一直在深入研究Python类中的运算符重载和特殊方法,我注意到许多内置函数都有其等效的特殊方法名称:

  • int(x)
    调用
    x.\uuuu int\uuuu()
  • next(x)
    调用Python2中的
    x.\uuuu next\uuuu()
    x.next()
但是,一对函数,即
tuple()
dict()
,没有任何等效函数。我知道还没有必要使用这种特殊方法,但在某些情况下,对类调用的
dict()
转换方法可能很有用。我该如何实现这一点?或者,对于试图使用这种逻辑的人,你会怎么评论

# I think this is quite interesting, so I shall post my own implementation of it as well

以最简单的形式,我可以尝试检索
对象。我还创建了一个名为
obj.\uuuuu dictionary\uuuu
的方法,它返回一个
dict
,但可以自定义返回的值和方式。我实现了一个小函数,尝试调用
obj.\uuuuu dictionary\uuuu
和其他方法的其他连续尝试:

def dct(obj=None, *args, **kwargs):
    if obj:
        try:
            r = obj.__dictionary__()
        except AttributeError:
            try:
                r = dict(obj)
            except TypeError:
                try:
                    r = obj.__dict__
                except AttributeError as e:
                    raise AttributeError(e) from None
                else:
                    return r
            else:
                return r
        else:
            return r
    else:
        return dict(*args, **kwargs)
为了演示,有一个小类封装了一个
“Person”

class Person:
    def __init__(self, name, age, job):
        self.name = name
        self.age = age
        self.job = job

    def __dictionary__(self):
        return {'name': self.name,
                'age': self.age,
                'job': self.job,
                'title': '{} {}'.format(self.job, self.name)}

p = Person('bob', 42, 'farmer')

现在考虑调用我的习惯>代码> DCT 函数对几个对象进行测试:

>>> dct(p)
{'name': 'bob', 'age': 42, 'job': 'farmer', 'title': 'farmer bob'}

>>> dct(item='apple', quantity=5)
{'item': 'apple', 'quantity': 5}

>>> dct([('username', 'admin'), ('password', '123')])
{'username': 'admin', 'password': '123'}

>>> dct({'a': 1, 'b': 2})
{'a': 1, 'b': 2}
正如你所看到的,它似乎工作在一个体面的方式。我知道,对于我简单的
Person
类演示,我可以简单地返回
p.uuu dict\uuuu
,但我添加了一个额外的
p.title
属性,该属性只存在于
dict
表单中,以表明这支持额外的定制。另外,如果我用
\uuuuuuuuuuuuuuuuuuuuuuuuuuu>定义
Person
类,那么
dct(p)
调用将失败

AttributeError: 'Person' object has no attribute '__dict__'
显然,我可以扩展
try/except
块来尝试访问
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>插槽,但这并不是我想要了解的重点:如果我在自定义
\uuuuu
按预期工作:

def __dictionary__(self):
    return {name: getattr(self, name, None)
            for name in self.__slots__}
选项1:
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
强制转换为
元组
dict
,或任何接受iterable的类型,都依赖于
\uuuuuuuuuuuuuuuuuuuuuuuuu
方法

class ListOfKeys():
    def __init__(self, lst):
        self.lst = lst

    def __iter__(self):
        for k in self.lst:
            yield (k, None)

lok = ListOfKeys([1, 2, 3])
d = dict(lok)

print(d) # {1: None, 2: None, 3: None}
这同样适用于元组

t = tuple(lok)

print(t) # ((1, None), (2, None), (3, None))
选项2:
\uu获取项目
或者,要转换为
dict
,您可以同时实现
键和

class ListOfKeys():
    def __init__(self, lst):
        self.lst = lst

    def keys(self):
        yield from self.lst

    def __getitem__(self, item):
        return None

lok = ListOfKeys([1, 2, 3])
d = dict(lok)

print(d) # {1: None, 2: None, 3: None}
选项3:两者都支持多种类型 最后,如果您希望您的类具有不同的行为来强制转换为
dict
tuple
,下面的示例演示
dict
将对
getitem
解决方案进行优先级排序

class Foo:
    def __iter__(self):
        yield 1

    def keys(self):
        yield 2

    def __getitem__(self, item):
        return 3

print(dict(Foo())) # {2: 3}
print(tuple(Foo())) # (1,)

dict
接受任何iterable对,假装语言实现了它没有实现的钩子有什么意义?
dict
构造函数不支持它,那么为什么不简单地使用一个
to_dict
方法呢?为了方便起见,我可以调用
dict()
任何东西,而不必担心它是否有自己的
to_dict
方法,然后用
方法将它包装起来,然后尝试:返回obj.to_dict(),除了AttributeError:return obj.u dict
。。。我的主要观点是你不应该添加你自己的“特殊”邓德方法。事实上,确切地说,这在
\uu iter\uuuuu
\uuuu getitem\uuuuuuuuu
中被明确禁止。这似乎是最具python风格的方法。它肯定比我的干净。只是一个小小的评论:如果想让dict()、tuple()和iter()都有不同的行为,该怎么办?比如说,迭代只会产生值,而不是值对。@NChauhan在这种情况下,您的方法是正确的,只需去掉dunder命名
.to_dict
。to tuple
@NChauhan dict实际为密钥getitem解决方案排定优先级,请参阅更新的答案