В большой программе, над которой я работал, я столкнулся с ошибкой атрибута:
line 154, in __ExtINT
DebugVar=Self.__Preset # Originally, I had Self.__Preset directly in an if statement. I added this line and put DebugVar in the if statement, so I could be sure what was causing the error.
AttributeError: '__Readitem' object has no attribute '_ReadItem__Preset'
Я был уверен, что это было установлено в функции __init__
, и потратил некоторое время, пытаясь понять, почему я получаю эту ошибку. Когда я обнаружил, что python использует словарь для хранения всех своих переменных, я поставил print(Self.__dict__)
перед строкой, вызвавшей ошибку, чтобы я мог видеть, какие атрибуты сделал существуют. Я был удивлен, увидев в словаре , '_Readitem__Preset': True}
. Почему тогда в ошибке говорится, что его не существует?
Я попробовал DebugVar=Self.__dict__['_Readitem__Preset']
вместо DebugVar=Self.__Preset
и получил:
line 154, in __ExtINT
DebugVar=Self.__dict__['_Readitem__Preset']
KeyError: '_Readitem__Preset'
Затем я попытался поставить self.__Preset=False
сразу после __init__
, чтобы быть уверенным, что он действительно существует.
Возможно, стоит упомянуть, что до того, как я попытался вручную извлечь значение из переменной, было отображено 2 словаря, что означает, что изначально код работал однажды. После того, как я изменил код, отображался только один словарь.
Есть ли кто-нибудь, кто сам сталкивался с этой проблемой или имеет какое-либо представление о том, почему это происходит?
Тогда почему «я» может относиться к другому случаю? Помните, я написал только «Я» (изначально). Почему мой класс будет отображаться с разными именами? @Rohi
На всякий случай, не могли бы вы указать свои переменные без искажения (т.е. без «__»).
Укажите переменную как Preset, а не как __Preset. Немного сложно отладить без всего кода, но я думаю, что это может быть проблема, связанная с искажением имени. Попробуйте и дайте мне знать. И я знаю, что это может быть далеко не все, но взгляните на это: stackoverflow.com/questions/20261517/…, опять же, это немного сложно, не видя всего кода.
@Rohi Спасибо, что заметили неправильный регистр для "I". Теперь я смог исправить код. По какой-то причине для моего атрибута использовался неправильный префикс. В качестве ответа я объяснил ошибку, но до сих пор не уверен, почему использовался неправильный префикс.
Это было больно.
Мне удалось несколько разобраться, почему я получаю ошибку, и исправить свой код. Вот описание того, как я получил ошибку и как я ее преодолел на случай, если кому-то интересно, или получить эту ошибку самостоятельно:
В моем коде есть класс, который по сути является категорией. Он хранит атрибуты, например, предопределен ли он или определен пользователем, содержит ли он какие-либо подкатегории, любые подкатегории, которые он может иметь, и т. д. Эти подкатегории представляют собой список, который содержит больше экземпляров этого класса. Затем мне пришлось создать другую его версию, которая записывает в файл при инициализации. Если бы я сделал то же самое, что и раньше, он бы записал данные, которые должны быть записаны в файл только один раз, в файл несколько раз. Я решил создать «подкласс», который будет работать немного иначе, чем его основной класс. Вот простой код, показывающий структуру, которую я пытался достичь:
class Main():
class __Sub():
def __init__(self,file,dat):
if isinstance(dat,tuple):
self.__trace=()
if False in (isinstance(i,int)for i in dat):self.__trace+=tuple((Main.__Sub(file,i),)for i in dat)
else:
self.__trace=dat
file.write(bytes(dat))
else:
self.__trace=(dat,)
file.write(bytes([dat]))
def __init__(self,file,dat):
File=open(file,"wb")
self.__trace=()
self.__trace+=tuple((Main.__Sub(File,i),)for i in dat)
File.close()
Main(input("Enter file name: "),(4,8,((32,71),255)))
Как я уже сказал в вопросе, python хранит свои переменные в словаре, и вы можете проверить атрибуты объекта с помощью .__dict__
. Если вы сделаете это, вы увидите, что каждый атрибут имеет имя своего класса в качестве префикса. Если вы попытаетесь запустить приведенный выше код, по какой-то причине он выйдет из строя, потому что он пытается использовать неправильный префикс для поиска атрибута.
Мое решение заключалось в том, чтобы удалить подкласс и сделать это с моим кодом:
class Main():
def __init__(self,file,dat):
if "BadPractice" in globals():
if isinstance(dat,tuple):
self.__trace=()
if False in (isinstance(i,int)for i in dat):self.__trace+=tuple((Main(file,i),)for i in dat)
else:
self.__trace=dat
file.write(bytes(dat))
else:
self.__trace=(dat,)
file.write(bytes([dat]))
else:
global BadPractice
BadPractice=None
self.__trace=()
self.__trace+=tuple((Main(file,i),)for i in dat)
file.close()
Main(open(input("Enter file name: "),"wb"),(4,8,((32,71,),255,),),)
Возможно, это не лучший способ сделать это, но он исправляет ошибку.
Как я понял, причина, по которой он использует префикс, заключается в том, что вы использовали «__» в начале атрибута. Это называется искажением имен и в основном используется для имитации защищенных атрибутов. Взгляните на ссылку, которую я разместил в основном разделе, я нашел довольно элегантное решение, чтобы исправить это.
ReadItem! = Readitem, обратите внимание на заглавную I. (в первом исключении)