Python 如何子类控制不可变实例中存储的数据
首先要了解Python中的__new__()
方法。当子类化一个不可变类型时,应该重写__new__()
方法而不是__init__()
方法。
__new__
方法在对象创建时被调用,而__init__
方法在初始化对象时被调用。这些都是特殊方法。
特殊方法允许我们在面向对象编程中做一些很酷的技巧。它们也被称为Dunder方法。这些方法以两个下划线(__)作为前缀和后缀来标识。
显示继承自int类的特殊方法
示例
使用fir(),我们可以打印出特殊方法-
print(dir(int))
输出
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__',
'__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__',
'__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__'
, '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__',
'__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__',
'__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__',
'__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__',
'__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_length', 'conjugate',
'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
__init__()
示例
让我们看一个使用__init__()
魔法方法实例化对象的示例-
class String:
# The magic method to initiate object
def __init__(self, string):
self.string = string
# Driver Code
if __name__ == '__main__':
# object creation
myStr = String('Demo')
# print object location
print(myStr)
输出
<__main__.String object at 0x7f34c97799d0>
继承不可变类型
示例
现在,让我们看一下Python子类如何控制在不可变实例中存储的数据。
from datetime import date
class FirstOfMonthDate(date):
"Always choose the first day of the month"
def __new__(cls, year, month, day):
return super().__new__(cls, year, month, 1)
class NamedInt(int):
"Allow text names for some numbers"
xlat = {'zero': 0, 'one': 1, 'ten': 10, 'fifteen': 15}
def __new__(cls, value):
value = cls.xlat.get(value, value)
return super().__new__(cls, value)
class TitleStr(str):
"Convert str to name suitable for a URL path"
def __new__(cls, s):
s = s.lower().replace(' ', '-')
s = ''.join([c for c in s if c.isalnum() or c == '-'])
return super().__new__(cls, s)
# Calling
print(FirstOfMonthDate(2022, 9, 8))
print(NamedInt('fifteen'))
print(NamedInt(18))
# Create a URL path
print(TitleStr('course for beginners'))
输出
2022-09-01
15
18
course-for-beginners