Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1743158
  • 博文数量: 297
  • 博客积分: 285
  • 博客等级: 二等列兵
  • 技术积分: 3006
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-06 22:04
个人简介

Linuxer, ex IBMer. GNU https://hmchzb19.github.io/

文章分类

全部博文(297)

文章存档

2020年(11)

2019年(15)

2018年(43)

2017年(79)

2016年(79)

2015年(58)

2014年(1)

2013年(8)

2012年(3)

分类: Python/Ruby

2019-03-02 15:47:50

我这里大部分代码出自The Python Master一书。

1. 在python的class里面,允许同名的方法存在。但是后定义的方法会覆盖掉先定义的方法.
例如:

点击(此处)折叠或打开

  1. class Dod1:
  2.     
  3.     def method1(self):
  4.         return "first definition"
  5.     
  6.     '''The second definition takes precedence because
  7.     it overwrites the first entry in the namespace
  8.     dictionary as the class definition is processed
  9.     '''
  10.     def method1(self):
  11.         return "second definition"
  12.     
  13.     
  14. def test_():
  15.     
  16.     d1 = Dod1()
  17.     print(d1.method1())

  18. test_()
test_() 会返回second definition。

又如: 

点击(此处)折叠或打开

  1. class T:
  2.     
  3.     def test1(self, second:str):
  4.         print("I am test1, and second is ", second)
  5.     
  6.     def test1(self):
  7.         print("I am test1")


  8. def test_():
  9.     
  10.     t = T()
  11.     a = range(1,5)
  12.     
  13.     try:
  14.         t.test1(a)
  15.     except TypeError as e:
  16.         print(e)
  17.     
  18.     t.test1()
  19.     
  20.     

  21. test_()
这一段代码的运行结果是

点击(此处)折叠或打开

  1. test1() takes 1 positional argument but 2 were given
  2. I am test1

2. 但是可以使用metaclass 避免这个情况,即不允许class里面有同名的method.
we can write metaclass which detects and prevents this.
rather than using a regular dictionary as the namespace object used during class construction,
we need a dictionary which raises an error when we try to assign to an existing key.
代码如下:

点击(此处)折叠或打开

  1. class OneShotDict(dict):
  2.     
  3.     def __init__(self, existing=None):
  4.         super().__init__()
  5.         if existing is not None:
  6.             for k, v in existing:
  7.                 self[k] = v
  8.         
  9.     def __setitem__(self, key, value):
  10.         if key in self:
  11.             raise KeyError("Cannot assign existing key {!r} "
  12.             "in {!r}".format(key, type(self).__name__))
  13.     
  14.         super().__setitem__(key, value)
  15.     

  16. class ProhibitDuplicateMeta(type):
  17.     
  18.     @classmethod
  19.     def __prepare__(mcs, name, bases):
  20.         return OneShotDict()
但是出错信息不够清晰如下:
KeyError: "Cannot assign existing key 'method1' in 'OneShotDict'"

改进以后则如下:

点击(此处)折叠或打开

  1. class OneShotClassNamespace(dict):
  2.     
  3.     def __init__(self, name, existing=None):
  4.         super().__init__()
  5.         self._name = name
  6.         if existing is not None:
  7.             for k,v in existing:
  8.                 self[k] = v
  9.     
  10.     def __setitem__(self, key, value):
  11.         if key in self:
  12.             raise TypeError("Can not reassign existing class "
  13.             "attribute {!r} of {!r}".format(key, self._name))
  14.     
  15.         super().__setitem__(key, value)


  16. class ProhibitDupInClass(type):
  17.     
  18.     @classmethod
  19.     def __prepare__(mcs, name, bases):
  20.         return OneShotClassNamespace(name)



  21. if __name__ == "__main__":
  22.     '''Can not define a class with duplicate methods using this metaclass'''
  23.     class Dod2(metaclass=ProhibitDupInClass):
  24.         
  25.         def method1(self):
  26.             return "first definition"
  27.         
  28.         def method1(self):
  29.             return "second definition"

这时候出错信息如下:
TypeError: Can not reassign existing class attribute 'method1' of 'Dod2'


点击(此处)折叠或打开

  1. if __name__ == "__main__":
  2.     '''Can not define a class with duplicate methods using this metaclass'''
  3.     class T2(metaclass=ProhibitDupInClass):
  4.         def test1(self, second:str):
  5.             print("I am test1, and second is ", second)
  6.         
  7.         def test1(self):
  8.             print("I am test1")

  9. #出错信息
  10. TypeError: Can not reassign existing class attribute 'test1' of 'T2'



阅读(1790) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~