인스턴스간에 클래스 데이터를 공유하지 않으려면 어떻게해야합니까?
내가 원하는 것은이 동작입니다.
class a:
list = []
x = a()
y = a()
x.list.append(1)
y.list.append(2)
x.list.append(3)
y.list.append(4)
print(x.list) # prints [1, 3]
print(y.list) # prints [2, 4]
물론 인쇄 할 때 실제로 발생하는 일은 다음과 같습니다.
print(x.list) # prints [1, 2, 3, 4]
print(y.list) # prints [1, 2, 3, 4]
분명히 그들은 수업 시간에 데이터를 공유하고 있습니다 a
. 원하는 동작을 수행하기 위해 별도의 인스턴스를 얻으려면 어떻게합니까?
당신은 이것을 원합니다 :
class a:
def __init__(self):
self.list = []
클래스 선언 내부의 변수를 선언하면 인스턴스 멤버가 아닌 "클래스"멤버가됩니다. __init__
메소드 내에서 선언 하면 멤버의 새 인스턴스가 객체의 모든 새 인스턴스와 함께 작성되어 원하는 동작입니다.
허용 된 답변은 효과가 있지만 조금 더 설명해도 아프지 않습니다.
인스턴스 생성시 클래스 속성은 인스턴스 속성이되지 않습니다. 값이 할당되면 인스턴스 속성이됩니다.
원래 코드에서는 list
인스턴스화 후 속성에 값이 할당되지 않습니다 . 따라서 클래스 속성으로 유지됩니다. 인스턴스화 후 호출 __init__
되므로 작업 내부 목록 정의 __init__
또는이 코드는 원하는 출력을 생성합니다.
>>> class a:
list = []
>>> y = a()
>>> x = a()
>>> x.list = []
>>> y.list = []
>>> x.list.append(1)
>>> y.list.append(2)
>>> x.list.append(3)
>>> y.list.append(4)
>>> print(x.list)
[1, 3]
>>> print(y.list)
[2, 4]
그러나 질문에서 혼란스러운 시나리오는 숫자와 문자열과 같은 불변의 객체에는 절대로 발생하지 않습니다. 할당없이 값을 변경할 수 없기 때문입니다. 예를 들어 문자열 속성 유형을 가진 원본과 비슷한 코드는 아무런 문제없이 작동합니다.
>>> class a:
string = ''
>>> x = a()
>>> y = a()
>>> x.string += 'x'
>>> y.string += 'y'
>>> x.string
'x'
>>> y.string
'y'
So to summarize: class attributes become instance attributes if and only if a value is assigned to them after instantiation, being in the __init__
method or not. This is a good thing because this way you can have static attributes if you never assign a value to an attribute after instantiation.
You declared "list" as a "class level property" and not "instance level property". In order to have properties scoped at the instance level, you need to initialize them through referencing with the "self" parameter in the __init__
method (or elsewhere depending on the situation).
You don't strictly have to initialize the instance properties in the __init__
method but it makes for easier understanding.
Although the accepted anwer is spot on, I would like to add a bit description.
Let's do a small exercise
first of all define a class as follows:
class A:
temp = 'Skyharbor'
def __init__(self, x):
self.x = x
def change(self, y):
self.temp = y
So what do we have here?
- We have a very simple class which has an attribute
temp
which is a string - An
__init__
method which setsself.x
- A change method sets
self.temp
Pretty straight forward so far yeah? Now let's start playing around with this class. Let's initialize this class first:
a = A('Tesseract')
Now do the following:
>>> print(a.temp)
Skyharbor
>>> print(A.temp)
Skyharbor
Well, a.temp
worked as expected but how the hell did A.temp
work? Well it worked because temp is a class attribute. Everything in python is an object. Here A is also an object of class type
. Thus the attribute temp is an attribute held by the A
class and if you change the value of temp through A
(and not through an instance of a
), the changed value is going to be reflected in all the instance of A
class. Let's go ahead and do that:
>>> A.temp = 'Monuments'
>>> print(A.temp)
Monuments
>>> print(a.temp)
Monuments
Interesting isn't it? And note that id(a.temp)
and id(A.temp)
are still the same.
Any Python object is automatically given a __dict__
attribute, which contains its list of attributes. Let's investigate what this dictionary contains for our example objects:
>>> print(A.__dict__)
{
'change': <function change at 0x7f5e26fee6e0>,
'__module__': '__main__',
'__init__': <function __init__ at 0x7f5e26fee668>,
'temp': 'Monuments',
'__doc__': None
}
>>> print(a.__dict__)
{x: 'Tesseract'}
Note that temp
attribute is listed among A
class's attributes while x
is listed for the instance.
So how come that we get a defined value of a.temp
if it is not even listed for the instance a
. Well that's the magic of __getattribute__()
method. In Python the dotted syntax automatically invokes this method so when we write a.temp
, Python executes a.__getattribute__('temp')
. That method performs the attribute lookup action, i.e. finds the value of the attribute by looking in different places.
The standard implementation of __getattribute__()
searches first the internal dictionary (dict) of an object, then the type of the object itself. In this case a.__getattribute__('temp')
executes first a.__dict__['temp']
and then a.__class__.__dict__['temp']
Okay now let's use our change
method:
>>> a.change('Intervals')
>>> print(a.temp)
Intervals
>>> print(A.temp)
Monuments
Well now that we have used self
, print(a.temp)
gives us a different value from print(A.temp)
.
Now if we compare id(a.temp)
and id(A.temp)
, they will be different.
Yes you must declare in the "constructor" if you want that the list becomes an object property and not a class property.
So nearly every response here seems to miss a particular point. Class variables never become instance variables as demonstrated by the code below. By utilizing a metaclass to intercept variable assignment at the class level, we can see that when a.myattr is reassigned, the field assignment magic method on the class is not called. This is because the assignment creates a new instance variable. This behavior has absolutely nothing to do with the class variable as demonstrated by the second class which has no class variables and yet still allows field assignment.
class mymeta(type):
def __init__(cls, name, bases, d):
pass
def __setattr__(cls, attr, value):
print("setting " + attr)
super(mymeta, cls).__setattr__(attr, value)
class myclass(object):
__metaclass__ = mymeta
myattr = []
a = myclass()
a.myattr = [] #NOTHING IS PRINTED
myclass.myattr = [5] #change is printed here
b = myclass()
print(b.myattr) #pass through lookup on the base class
class expando(object):
pass
a = expando()
a.random = 5 #no class variable required
print(a.random) #but it still works
IN SHORT Class variables have NOTHING to do with instance variables.
More clearly They just happen to be in the scope for lookups on instances. Class variables are in fact instance variables on the class object itself. You can also have metaclass variables if you want as well because metaclasses themselves are objects too. Everything is an object whether it is used to create other objects or not, so do not get bound up in the semantics of other languages usage of the word class. In python, a class is really just an object that is used to determine how to create other objects and what their behaviors will be. Metaclasses are classes that create classes, just to further illustrate this point.
To protect your variable shared by other instance you need to create new instance variable each time you create an instance. When you are declaring a variable inside a class it's class variable and shared by all instance. If you want to make it for instance wise need to use the init method to reinitialize the variable as refer to the instance
From Python Objects and Class by Programiz.com:
__init__()
function. This special function gets called whenever a new object of that class is instantiated.This type of function is also called constructors in Object Oriented Programming (OOP). We normally use it to initialize all the variables.
For example:
class example:
list=[] #This is class variable shared by all instance
def __init__(self):
self.list = [] #This is instance variable referred to specific instance
참고URL : https://stackoverflow.com/questions/1680528/how-to-avoid-having-class-data-shared-among-instances
'development' 카테고리의 다른 글
파이썬 커맨드 라인에서 나가기 (0) | 2020.07.03 |
---|---|
단축키를 사용하여 Google 검색 결과 탐색 (0) | 2020.07.03 |
Matplotlib 컬러 바 크기를 그래프와 일치하도록 설정 (0) | 2020.07.02 |
파이썬에서 "내부 예외"(트레이스 백 포함)? (0) | 2020.07.02 |
ASP.NET MVC 예 / 아니요 바운드 모델 MVC가있는 라디오 버튼 (0) | 2020.07.02 |