Programing

클래스와 인스턴스 변수의 차이점은 무엇입니까?

lottogame 2020. 12. 8. 07:36
반응형

클래스와 인스턴스 변수의 차이점은 무엇입니까?


Python에서 클래스와 인스턴스 변수의 차이점은 무엇입니까?

class Complex:
    a = 1

class Complex:
    def __init__(self):
        self.a = 1

호출 사용 : x = Complex().a두 경우 모두 x를 1에 할당합니다.

에 대한보다 깊이있는 대답 __init__()과는 self이해할 수있을 것이다.


클래스 블록을 작성할 때 클래스 속성 (또는 클래스 변수)을 생성합니다. 정의한 메서드를 포함하여 클래스 블록에 할당 한 모든 이름 def은 클래스 속성이됩니다.

클래스 인스턴스가 생성 된 후 인스턴스에 대한 참조가있는 모든 항목은 인스턴스 속성을 생성 할 수 있습니다. 메서드 내에서 "현재"인스턴스는 거의 항상 이름에 바인딩되어 있으므로 self이를 "자기 변수"라고 생각하는 것입니다. 일반적으로 객체 지향 설계에서, 클래스에 부착 된 코드는 그래서 거의 모든 인스턴스 속성 할당은 수신 인스턴스에 대한 참조 사용 방법 내부에서 수행되고, 그 클래스의 인스턴스의 속성을 제어 할 수 있습니다하도록되어 self의 매개 변수를 방법.

클래스 속성은 종종 Java, C # 또는 C ++와 같은 언어에서 볼 수있는 정적 변수 (또는 메서드)와 비교됩니다 . 그러나 더 깊은 이해를 목표로한다면 클래스 속성을 정적 변수와 "동일"한 것으로 생각하지 않을 것입니다. 동일한 목적으로 자주 사용되지만 기본 개념은 상당히 다릅니다. 이에 대한 자세한 내용은 줄 아래 "고급"섹션을 참조하십시오.

예!

class SomeClass:
    def __init__(self):
        self.foo = 'I am an instance attribute called foo'
        self.foo_list = []

    bar = 'I am a class attribute called bar'
    bar_list = []

이 블록을 실행 한 후, 거기 클래스 SomeClass3 개 클래스 속성으로, : __init__, bar, 및 bar_list.

그런 다음 인스턴스를 생성합니다.

instance = SomeClass()

이 경우 SomeClass__init__메서드가 실행되어 self매개 변수에 새 인스턴스를 수신합니다 . 이 메서드는 foofoo_list. 그런 다음이 인스턴스가 instance변수에 할당 되므로 두 인스턴스 속성 foo을 가진 사물에 바인딩됩니다 foo_list.

그러나:

print instance.bar

제공합니다 :

I am a class attribute called bar

어떻게 이런일이 일어 났습니까? 도트 구문을 통해 속성 검색 하려고 할 때 속성이 존재하지 않으면 Python은 어쨌든 요청을 수행하기 위해 여러 단계를 거칩니다. 다음으로 시도 할 것은 인스턴스 클래스의 클래스 속성 을 살펴 보는 것 입니다. 이 경우에서 속성 bar찾았 SomeClass으므로 반환했습니다.

메서드 호출이 작동하는 방식이기도합니다. mylist.append(5)를 들어을 호출 할 때에는 mylist라는 속성이 없습니다 append. 그러나 클래스 의는 mylist않습니다, 그것은 방법 개체에 바인딩입니다. 해당 메서드 객체는 mylist.append비트에 의해 반환 된 다음 비트 (5)는 인수를 사용하여 메서드를 호출합니다 5.

이것이 유용한 방법은의 모든 인스턴스가 SomeClass동일한 bar속성에 액세스 할 수 있다는 것입니다. 백만 개의 인스턴스를 만들 수 있지만 모두 찾을 수 있기 때문에 하나의 문자열 만 메모리에 저장하면됩니다.

하지만 조심해야합니다. 다음 작업을 살펴보십시오.

sc1 = SomeClass()
sc1.foo_list.append(1)
sc1.bar_list.append(2)

sc2 = SomeClass()
sc2.foo_list.append(10)
sc2.bar_list.append(20)

print sc1.foo_list
print sc1.bar_list

print sc2.foo_list
print sc2.bar_list

이것이 무엇을 인쇄한다고 생각하십니까?

[1]
[2, 20]
[10]
[2, 20]

This is because each instance has its own copy of foo_list, so they were appended to separately. But all instances share access to the same bar_list. So when we did sc1.bar_list.append(2) it affected sc2, even though sc2 didn't exist yet! And likewise sc2.bar_list.append(20) affected the bar_list retrieved through sc1. This is often not what you want.


Advanced study follows. :)

To really grok Python, coming from traditional statically typed OO-languages like Java and C#, you have to learn to rethink classes a little bit.

In Java, a class isn't really a thing in its own right. When you write a class you're more declaring a bunch of things that all instances of that class have in common. At runtime, there's only instances (and static methods/variables, but those are really just global variables and functions in a namespace associated with a class, nothing to do with OO really). Classes are the way you write down in your source code what the instances will be like at runtime; they only "exist" in your source code, not in the running program.

In Python, a class is nothing special. It's an object just like anything else. So "class attributes" are in fact exactly the same thing as "instance attributes"; in reality there's just "attributes". The only reason for drawing a distinction is that we tend to use objects which are classes differently from objects which are not classes. The underlying machinery is all the same. This is why I say it would be a mistake to think of class attributes as static variables from other languages.

But the thing that really makes Python classes different from Java-style classes is that just like any other object each class is an instance of some class!

In Python, most classes are instances of a builtin class called type. It is this class that controls the common behaviour of classes, and makes all the OO stuff the way it does. The default OO way of having instances of classes that have their own attributes, and have common methods/attributes defined by their class, is just a protocol in Python. You can change most aspects of it if you want. If you've ever heard of using a metaclass, all that is is defining a class that is an instance of a different class than type.

The only really "special" thing about classes (aside from all the builtin machinery to make them work they way they do by default), is the class block syntax, to make it easier for you to create instances of type. This:

class Foo(BaseFoo):
    def __init__(self, foo):
        self.foo = foo

    z = 28

is roughly equivalent to the following:

def __init__(self, foo):
    self.foo = foo

classdict = {'__init__': __init__, 'z': 28 }

Foo = type('Foo', (BaseFoo,) classdict)

And it will arrange for all the contents of classdict to become attributes of the object that gets created.

So then it becomes almost trivial to see that you can access a class attribute by Class.attribute just as easily as i = Class(); i.attribute. Both i and Class are objects, and objects have attributes. This also makes it easy to understand how you can modify a class after it's been created; just assign its attributes the same way you would with any other object!

In fact, instances have no particular special relationship with the class used to create them. The way Python knows which class to search for attributes that aren't found in the instance is by the hidden __class__ attribute. Which you can read to find out what class this is an instance of, just as with any other attribute: c = some_instance.__class__. Now you have a variable c bound to a class, even though it probably doesn't have the same name as the class. You can use this to access class attributes, or even call it to create more instances of it (even though you don't know what class it is!).

And you can even assign to i.__class__ to change what class it is an instance of! If you do this, nothing in particular happens immediately. It's not earth-shattering. All that it means is that when you look up attributes that don't exist in the instance, Python will go look at the new contents of __class__. Since that includes most methods, and methods usually expect the instance they're operating on to be in certain states, this usually results in errors if you do it at random, and it's very confusing, but it can be done. If you're very careful, the thing you store in __class__ doesn't even have to be a class object; all Python's going to do with it is look up attributes under certain circumstances, so all you need is an object that has the right kind of attributes (some caveats aside where Python does get picky about things being classes or instances of a particular class).

That's probably enough for now. Hopefully (if you've even read this far) I haven't confused you too much. Python is neat when you learn how it works. :)


What you're calling an "instance" variable isn't actually an instance variable; it's a class variable. See the language reference about classes.

In your example, the a appears to be an instance variable because it is immutable. It's nature as a class variable can be seen in the case when you assign a mutable object:

>>> class Complex:
>>>    a = []
>>>
>>> b = Complex()
>>> c = Complex()
>>> 
>>> # What do they look like?
>>> b.a
[]
>>> c.a
[]
>>> 
>>> # Change b...
>>> b.a.append('Hello')
>>> b.a
['Hello']
>>> # What does c look like?
>>> c.a
['Hello']

If you used self, then it would be a true instance variable, and thus each instance would have it's own unique a. An object's __init__ function is called when a new instance is created, and self is a reference to that instance.

참고URL : https://stackoverflow.com/questions/8959097/what-is-the-difference-between-class-and-instance-variables

반응형