Я немного запутался в области видимости классов Python.Также о его связи с потоками.Ниже приведен минимальный рабочий пример.Я создал экземпляр B и передал его экземпляру A.
Как я понимаю, A должен создать свою собственную локальную копию B_instance.По-видимому, этого не происходит, поскольку каждый раз, когда я изменяю атрибут B_instance любым мыслимым способом, я вижу изменение как в A_instance, так и в B_instance (печатает 1-6).Означает ли это, что A_instance.other_class считается глобальным?Есть ли способ сделать A_instance.other_class локальным?так что его изменение не изменит сам B_instance.
Вторая часть вопроса связана с многопоточностью.Я знаю, что доступ к атрибутам класса не является потокобезопасным, поэтому я использую блокировки.Однако, если вы посмотрите на операторы print, я бы ожидал, что «блокировка снята» будет напечатана перед «изменением в основном потоке».Что мне не хватает?Кажется, что обе блокировки блокируют что-то еще, поскольку блокировка в основном потоке может быть получена, даже если в A_instance все еще действует.Мне кажется, что это противоречит моим выводам из первой части.
Можно ли получить блокировку для всего объекта, а не только его атрибута или метода?
class A:
def __init__(self, other_class):
self.lock = threading.Lock()
self.other_class = other_class
def increment_B(self):
self.other_class.B_attr_1 += 1
def set_B(self):
self.other_class.B_attr_1 = 10
def thread_modify_attr(self):
self.lock.acquire()
self.other_class.B_attr_1 = "modified by class"
time.sleep(10)
self.lock.release()
print("lock released")
class B:
def __init__(self):
self.B_attr_1 = 0
if __name__ == "__main__":
B_instance = B()
A_instance = A(B_instance)
print("1:", B_instance.B_attr_1)
A_instance.other_class.B_attr_1 += 1
print("2:", B_instance.B_attr_1)
A_instance.other_class.B_attr_1 = 10
print("3:", B_instance.B_attr_1)
A_instance.increment_B()
print("4:", B_instance.B_attr_1)
A_instance.set_B()
print("5:", B_instance.B_attr_1)
B_instance.B_attr_1 = 0
print("6:", A_instance.other_class.B_attr_1)
lock = threading.Lock()
t = threading.Thread(target=A_instance.thread_modify_attr)
t.start()
print("thread started")
print(B_instance.B_attr_1)
lock.acquire()
B_instance.B_attr_1 = "modified by main thread"
lock.release()
print(B_instance.B_attr_1)
print("done")
t.join()
Результаты:
1: 0
2: 1
3: 10
4: 11
5: 10
6: 0
thread started
modified by class
modified by main thread
done
lock released
Кто-нибудь знает о каком-то хорошем месте, чтобы прочитать подробности о области видимости Python, я был бы признателен.