파이썬 변수 선언


88

Python을 배우고 몇 가지 기본적인 의문이 있습니다.

1. 변수 선언 (여기 경로)을 보았습니다.

class writer:
    path = ""

때로는 명시 적 선언이 없지만 __init__.

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

의 목적을 이해 __init__하지만 다른 함수에서 변수를 선언하는 것이 좋습니다.

2. 사용자 정의 유형을 보유하기 위해 변수를 생성하려면 어떻게해야합니까?

class writer:
    path = "" # string value
    customObj = ??

12
그리고 두 번째 질문과 관련하여 Python에서 변수에는 유형이 없습니다. 따라서 모든 변수는 사용자 지정 개체를 보유 할 수 있습니다.
jpaugh

4
이름 / 식별자를 변수 로 생각하지 않으면 도움이 될 것 입니다. 그들은있는 참조 객체
존 라 Rooy

2
그들을 위해 @gnibbler 또는 이름 ...
detly

1
@detly, 나는 이름이 나쁜 선택이라고 생각합니다. 객체가 여러 참조를 가질 수있는 반면 상황이 일반적으로 하나의 이름이
존 라 Rooy

2
@JohnClements,하지만 파이썬은 수학처럼 작동하지 않습니다. 파이썬을 이해하려면 __name__속성이있는 객체 에 "이름"이 있다는 것을 알아야합니다 . 모든 개체에 __name__속성 이있는 것은 아니지만 여전히 참조를 가질 수 있습니다. 우리가 "참조"를 "이름"이라고 부르기 시작하면 우리는 초보자들에게 해를 끼치는 것입니다.
John La Rooy

답변:


206

좋아, 우선 먼저.

파이썬에는 "변수 선언"이나 "변수 초기화"와 같은 것이 없습니다.

단순히 "할당"이라고 부르는 것이 있지만 아마도 "이름 지정"이라고 불러야 할 것입니다.

할당은 "이제 왼쪽에있는이 이름은 이전에 언급 한 내용에 관계없이 오른쪽을 평가 한 결과를 나타냅니다 (있는 경우)"를 의미합니다.

foo = 'bar' # the name 'foo' is now a name for the string 'bar'
foo = 2 * 3 # the name 'foo' stops being a name for the string 'bar',
# and starts being a name for the integer 6, resulting from the multiplication

따라서 Python의 이름 ( "변수"보다 나은 용어)에는 관련 유형이 없습니다. 가치는 그렇습니다. 유형에 관계없이 모든 항목에 동일한 이름을 다시 적용 할 수 있지만 여전히 유형에 따라 동작하는 동작이 있습니다. 이름은 단순히 값 (객체)을 참조하는 방법입니다. 이것은 두 번째 질문에 대한 답 입니다. 사용자 지정 유형을 유지하기 위해 변수를 만들지 않습니다 . 특정 유형을 보유하기 위해 변수를 만들지 않습니다. 변수를 전혀 "생성"하지 않습니다. 개체에 이름을 부여합니다.

두 번째 요점 : Python은 클래스와 관련하여 매우 간단한 규칙을 따릅니다. 이는 실제로 Java, C ++ 및 C #과 같은 언어보다 훨씬 일관 적입니다 . class블록 내에서 선언 된 모든 것은 클래스의 일부입니다 . 따라서 def여기에 작성된 함수 ( )는 메소드입니다. 즉, Java, C ++ 및 C #에서와 같이 클래스 객체의 일부 (인스턴스별로 저장되지 않음)입니다. 그러나 여기에 다른 이름 수업의 일부입니다. 다시 말하지만, 이름은 이름 일 뿐이며 연관된 유형이 없으며 함수도 Python에서 객체 입니다. 그러므로:

class Example:
    data = 42
    def method(self): pass

클래스도 파이썬에서 객체 입니다.

이제 우리는 모든 사물의 클래스를 나타내는 라는 객체를 만들었습니다 . 이 개체에는 두 개의 사용자 제공 속성 (C ++에서는 "멤버", C #에서는 "필드 또는 속성 또는 메서드", Java에서는 "필드 또는 메서드")이 있습니다. 그 중 하나는 이름이 지정 되고 정수 값을 저장합니다 . 다른 하나는 이름이 이고 함수 객체를 저장합니다. (Python이 자동으로 추가하는 몇 가지 속성이 더 있습니다.)ExampleExampledata42method

그러나 이러한 속성은 여전히 ​​실제로 개체의 일부가 아닙니다. 기본적으로 객체는 더 이상 나눌 수없는 것들에 도달 할 때까지 더 많은 이름 (속성 이름)의 묶음 일뿐입니다. 따라서 값은 클래스의 다른 인스턴스간에 공유 될 수 있으며 의도적으로 설정 한 경우 다른 클래스의 개체 간에도 공유 될 수 있습니다.

인스턴스를 만들어 보겠습니다.

x = Example()

이제 우리 x는의 인스턴스 인 라는 별도의 개체를 갖게되었습니다 Example. datamethod개체의 실제로 일부 있지만, 우리는 여전히 그들을 통해 찾아 볼 수 x있기 때문에 파이썬이 장면 뒤에 않는 몇 가지 마법. 특히을 조회 할 때 method대신 "바운드 메소드"를 얻습니다 (이를 호출 할 때 매개 변수 x로 자동으로 전달되며 직접 self조회하면 발생할 수 없음 Example.method).

사용하려고하면 x.data어떻게 되나요?

우리가 그것을 조사 할 때, 그것은 먼저 객체에서 조회됩니다. 객체에서 찾을 수없는 경우 Python은 클래스를 찾습니다.

그러나에 할당하면 x.data Python은 객체에 속성을 생성합니다. 그것은 것입니다 하지 클래스 '속성을 대체합니다.

이를 통해 객체 초기화 를 수행 할 수 있습니다 . Python은 __init__새 인스턴스가 생성 될 때 자동으로 클래스의 메서드를 호출합니다 . 이 메서드에서는 간단히 속성에 할당하여 각 개체의 해당 속성에 대한 초기 값을 설정할 수 있습니다.

class Example:
    name = "Ignored"
    def __init__(self, name):
        self.name = name
    # rest as before

이제를 name만들 때 를 지정해야 Example하며 각 인스턴스에는 고유 한 name. 파이썬은 인스턴스의 속성이 먼저 발견 될 것이기 때문에 Example.name우리 .name가 인스턴스를 조회 할 때마다 클래스 속성을 무시합니다 .

마지막 경고 : 수정 (변이)과 할당은 서로 다릅니다!

Python에서 문자열은 변경할 수 없습니다. 수정할 수 없습니다. 당신이 할 때 :

a = 'hi '
b = a
a += 'mom'

당신은 변경되지 않습니다 원래 '안녕하세요'문자열입니다. 파이썬에서는 불가능합니다. 대신, 당신은 만들 문자열을 'hi mom', 그리고 원인 a의 이름 인 중지 'hi '하고, 이름있는 시작 'hi mom'대신. 우리가 만든 b이름을 'hi '뿐만 아니라, 그리고 재 - 적용 후 a이름을 b아직 이름입니다 'hi '때문에, 'hi '여전히 존재하고 변경되지 않았습니다.

그러나 목록은 변경할 수 있습니다.

a = [1, 2, 3]
b = a
a += [4]

이제 b[1, 2, 3, 4]도 마찬가지입니다. 왜냐하면 우리가 b그 이름과 같은 이름을 만들고 그 이름을 a변경했기 때문입니다. aPython은 단순히 +=목록을 다르게 취급하기 때문에 이름을 지정할 새 목록을 만들지 않았습니다 .

클래스 속성으로 목록이 있고 인스턴스를 사용하여 목록을 수정 한 경우 변경 사항이 다른 모든 인스턴스에서 "보이기"때문에 이것은 객체에 중요합니다. 이는 (a) 데이터가 실제로 인스턴스 객체가 아니라 클래스 객체의 일부이기 때문입니다. (b) 목록을 수정하고 단순 할당을하지 않았기 때문에 클래스 속성을 숨기는 새 인스턴스 속성을 만들지 않았습니다.


12
이것이 우리가 그들을 '식별자' 라고 부르는 이유 입니다. :-)
Martijn Pieters

결국 문자열 예제에서 @Karl_Knechtel, 'b'로 이름을 지정하지 않으면 'hi'는 어떻게됩니까? 이것은 메모리 누수입니까?
heretoinfinity

2
@heretoinfinity : 아니오; 파이썬은 무료 도달 할 수없는 객체에 가비지 수집을 사용합니다
존 클레멘트에게

변수 선언은 youtube.com/watch?v=ao2N37E-D9s 동영상에 잘 설명되어 있습니다.
이샤 칸

답을 보려면이 비디오를 확인하십시오. youtube.com/…
Thao N

23

6 년 늦었을 수도 있지만 Python 3.5 이상에서는 다음과 같은 변수 유형을 선언합니다.

variable_name: type_name

아니면 이거:

variable_name # type: shinyType

따라서 귀하의 경우 ( CustomObject클래스가 정의 된 경우) 다음을 수행 할 수 있습니다.

customObj: CustomObject

자세한 정보는 이것 또는 저것 을 참조하십시오.


이것은 전통적인 의미의 선언이 아니지만 정적 유형 검사기 및 IDE가 지적 할 수 있지만 여전히 실행되고 실패하는 힌트입니다.
PhilHibbs

@PhilHibbs 그래도 실패하지 않습니다. "실패"란 무엇을 의미합니까?
O. Aroesti 20.

내 말은 당신이 할 경우이며 a: int다음 a='hello, world!'할이 INT 만 지금까지의 int로 선언되지 않도록, 그것은 실패하지 않습니다. 나는 "실패하지 않을 것이다"라고 말 했어야했다. 당신이 한 경우 a: int, a='hello, world!', a=a+1그 정적 타입 언어에서 컴파일에 실패한다.
PhilHibbs

22

Python에서 새 변수를 선언 할 필요가 없습니다. 함수 나 모듈의 변수에 대해 이야기하고 있다면 선언이 필요하지 않습니다. 필요한 곳에 값을 지정하십시오 mymagic = "Magic".. Python의 변수는 모든 유형의 값을 보유 할 수 있으며이를 제한 할 수 없습니다.

귀하의 질문은 클래스, 객체 및 인스턴스 변수에 대해 구체적으로 묻습니다. 인스턴스 변수를 만드는 관용적 인 방법은 __init__메서드에 있고 다른 곳에는 없습니다 . 다른 메서드 나 관련없는 코드에서도 새 인스턴스 변수를 만들 있지만 그것은 나쁜 생각입니다. 코드를 추론하거나 유지하기가 어렵습니다.

예를 들면 다음과 같습니다.

class Thing(object):

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

쉬운. 이제이 클래스의 인스턴스에는 magic속성이 있습니다.

thingo = Thing("More magic")
# thingo.magic is now "More magic"

클래스 자체의 네임 스페이스에 변수를 생성하면 완전히 다른 동작이 발생합니다. 기능적으로 다르며 특별한 이유가있는 경우에만 수행해야합니다. 예를 들면 :

class Thing(object):

    magic = "Magic"

    def __init__(self):
        pass

이제 시도해보십시오.

thingo = Thing()
Thing.magic = 1
# thingo.magic is now 1

또는:

class Thing(object):

    magic = ["More", "magic"]

    def __init__(self):
        pass

thing1 = Thing()
thing2 = Thing()
thing1.magic.append("here")
# thing1.magic AND thing2.magic is now ["More", "magic", "here"]

이는 클래스 자체의 네임 스페이스가 클래스에서 생성 된 개체의 네임 스페이스와 다르기 때문입니다. 좀 더 조사해 보도록하겠습니다.

집으로 가져가는 메시지는 관용적 인 Python이 (a) __init__메서드 에서 객체 속성을 초기화 하고 (b) 필요에 따라 클래스의 동작을 문서화한다는 것입니다. 지금까지 작성한 모든 내용에 대해 완전한 Sphinx 수준 문서의 문제를 겪을 필요는 없지만, 적어도 자신이나 다른 사람이 그것을 선택하는 데 필요한 세부 사항에 대한 의견은 몇 개 있습니다.


12

범위 지정을 위해 다음을 사용합니다.

custom_object = None

1

변수에는 범위가 있으므로 함수에 특정한 변수를 갖는 것이 적절합니다. 그 정의에 대해 항상 명시 할 필요는 없습니다. 보통 그냥 사용할 수 있습니다. 목록에 추가하는 것과 같이 변수 유형에 특정한 작업을 수행하려는 경우에만 변수를 사용하기 전에 정의해야합니다. 이것의 전형적인 예.

list = []
for i in stuff:
  list.append(i)

그건 그렇고, 이것은 목록을 설정하는 좋은 방법이 아닙니다. 다음과 같이 말하는 것이 좋습니다.

list = [i for i in stuff] # list comprehension

...하지만 나는 빗나 갔다.

다른 질문입니다. 사용자 지정 개체는 클래스 자체 여야합니다.

class CustomObject(): # always capitalize the class name...this is not syntax, just style.
  pass
customObj = CustomObject()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.