python metaclass_关于 Python 的元类,为什么设置了__metaclass__不起作用?

说实话,写的 Python 代码也不少,小到脚本、爬虫,大到 web 框架,但是写来写去,却连最原始的东西也还没有搞清楚,今天看了很多关于 Python 元类的文章,也领悟了一些东西,但是还是有疑问。

背景:我今天看了好几遍文章,博客园+简书,都是关于元类的,但是我发现这几篇高排名的文章好像写的东西很类似,连例子都是一样的,我开始以为是同一个人写的,后来发现原来原始的例子在 stackoverflow 中,看来都是从这里学习之后自己分享的。

其他的例子我都能懂,但是下面这段代码,我 Python3 运行却不是预期的输出,难道下面的代码是 Python2 才能按照注释里面的预期输出吗?

def upper_attr(future_class_name, future_class_parents, future_class_attr):

"""

Return a class object, with the list of its attribute turned

into uppercase.

"""

# pick up any attribute that doesn't start with '__' and uppercase it

uppercase_attr = {}

for name, val in future_class_attr.items():

if not name.startswith('__'):

uppercase_attr[name.upper()] = val

else:

uppercase_attr[name] = val

# let `type` do the class creation

return type(future_class_name, future_class_parents, uppercase_attr)

__metaclass__ = upper_attr # this will affect all classes in the module

class Foo(): # global __metaclass__ won't work with "object" though

# but we can define __metaclass__ here instead to affect only this class

# and this will work with "object" children

bar = 'bip'

print(hasattr(Foo, 'bar'))

# Out: False

print(hasattr(Foo, 'BAR'))

# Out: True

我 Python3 的结果是

True

False

这让我发现设置__metaclass__根本没有起作用,所以,我的问题是,__metaclass__到底怎么使用???????????

有兴趣的还可以看看我自己的代码(我在自定义一个元类,用途是给 unittest 的用例添加序号)

import unittest

LONG = 5

class Meta(type):

def __new__(cls, class_name, class_parents, class_attrs):

id = 1

_others = {}

_attrs = {}

for k, v in class_attrs.items():

if k.startswith('__') and k.endswith('__'):

_others[k] = v

else:

if k.startswith('test_'):

k = k.replace('test_', "test_{}_".format(str(id).zfill(LONG)))

id += 1

_attrs[k] = v

_attrs.update(_others)

return type.__new__(cls, class_name, class_parents, _attrs)

def change_name(cls_name, cls_parents, cls_attrs):

id = 1

_others = {}

_attrs = {}

for k, v in cls_attrs.items():

if k.startswith('__') and k.endswith('__'):

_others[k] = v

else:

if k.startswith('test_'):

k = k.replace('test_', "test_{}_".format(str(id).zfill(LONG)))

id += 1

_attrs[k] = v

_attrs.update(_others)

return type(cls_name, cls_parents, _attrs)

class Student1(unittest.TestCase):

def test_kkk(self):

return 1

def test_bbb(self):

return 3

class Student2(unittest.TestCase, metaclass=change_name):

def test_kkk(self):

return 1

def test_bbb(self):

return 3

class Student3(unittest.TestCase, metaclass=Meta):

def test_kkk(self):

self.assertEqual(1, 1)

def test_bbb(self):

self.assertEqual(1,1)

class Student4(unittest.TestCase):

__metaclass__ = Meta

def test_kkk(self):

self.assertEqual(1, 1)

def test_bbb(self):

self.assertEqual(1,1)

print(dir(Student1))

print(dir(Student2))

print(dir(Student3))

print(dir(Student4))

上面的 4 个打印结果的最后一段是下面这样的,2 和 3 符合预期结果,但是 4 不符合,4 的结果跟我问的一样,我发现我设置__metaclass__属性根本不起作用。

[... 'test_bbb', 'test_kkk']

[... 'test_00001_bbb', 'test_00002_kkk']

[... 'test_00001_bbb', 'test_00002_kkk']

[... 'test_bbb', 'test_kkk']

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值