Ответ 1
Проблема заключается в том, что вы наследуете от str
, что, вероятно, реализует __new__
, что означает, что даже если вы избежали вызова родительского конструктора в своем классе, базовый объект C все еще инициализируется им.
Теперь join
, вероятно, проверяет, имеет ли он подкласс str
и, будучи внедренным на C, он напрямую обращается к базовой структуре C или использует другую связанную с str
функцию, которая обходит __str__
и __repr__
(подумайте об этом: если значение является строкой или строковым подклассом, почему код вызывает __str__
или __repr__
, чтобы получить его значение? Он просто обращается к основному массиву символов каким-то образом!)
Чтобы исправить это: do не наследовать от str
! К сожалению, это означает, что вы не сможете использовать этот объект в точности как строка в некоторых ситуациях, но это почти неизбежно.
Альтернативой, которая может работать, является реализация __new__
и передача другого значения методу str
__new__
:
class secret(str):
def __new__(cls, initializer):
return super(secret, cls).__new__(cls, 'X'*len(initializer))
def __init__(self, initializer):
self.text = initializer
def __repr__(self):
return "'{}'".format("R"*len(self))
def __str__(self):
return "S"*len(self)
def __add__(self, other):
return str(self) + other
def __radd__(self, other):
return other + str(self)
Результат:
In [19]: pwd = secret('nothidden')
In [20]: print("The passwort is " + pwd) # The passwort is SSSSSSSSS
...: print(pwd + " is the passwort.") # SSSSSSSSS is the password.
...:
...: print("The passwort is {}.".format(pwd)) # The password is SSSSSSSSS.
...: print(["The", "passwort", "is", pwd]) # ['The', 'password', 'is', 'RRRRRRRRR']
...: print(pwd[:])
The passwort is SSSSSSSSS
SSSSSSSSS is the passwort.
The passwort is SSSSSSSSS.
['The', 'passwort', 'is', 'RRRRRRRRR']
XXXXXXXXX
In [21]: print(" ".join(["The", "password", "is", pwd]))
The password is XXXXXXXXX
Однако я не вижу, как это полезно. Я имею в виду: цель этого класса - избежать ошибок программирования, которые в конечном итоге отображают конфиденциальную информацию? Но тогда срабатывание исключения будет лучше, чтобы вы могли идентифицировать ошибки! Для этого лучше всего raise NotImplementedError
внутри __str__
и __repr__
вместо бесшумного предоставления бесполезного значения... убедитесь, что вы не просачиваете секрет, но поиск ошибок становится очень трудным.