수색…


소개

파이썬은 애매 모호하고 예기치 않은 행동없이 명확하고 읽기 쉬운 언어입니다. 불행히도, 이러한 목표는 모든 경우에 성취 할 수있는 것이 아니며, 그렇기 때문에 파이썬은 여러분이 기대했던 것과 다른 일을 할 수있는 몇 가지 코너 케이스를 가지고 있습니다.

이 섹션에서는 파이썬 코드 작성시 발생할 수있는 몇 가지 문제점을 보여줍니다.

반복되는 시퀀스 변경하기

for 루프는 시퀀스를 반복하므로 루프 내부에서이 시퀀스를 변경하면 예기치 않은 결과가 발생할 수 있습니다 (특히 요소를 추가하거나 제거 할 때).

alist = [0, 1, 2]
for index, value in enumerate(alist):
    alist.pop(index)
print(alist)
# Out: [1]

참고 : list.pop() 은 목록에서 요소를 제거하는 데 사용됩니다.

두 번째 요소는 반복이 색인을 순서대로 통과하기 때문에 삭제되지 않았습니다. 위의 루프는 다음과 같은 결과를 두 번 반복합니다.

# Iteration #1
index = 0
alist = [0, 1, 2]
alist.pop(0) # removes '0'

# Iteration #2
index = 1
alist = [1, 2]
alist.pop(1) # removes '2'

# loop terminates, but alist is not empty:
alist = [1]

인덱스가 증가하는 방향으로 반복하면서 인덱스가 변경되기 때문에이 문제가 발생합니다. 이 문제를 피하기 위해 루프를 거꾸로 반복 할 수 있습니다.

alist = [1,2,3,4,5,6,7]
for index, item in reversed(list(enumerate(alist))):
    # delete all even items
    if item % 2 == 0:
        alist.pop(index)
print(alist)
# Out: [1, 3, 5, 7]

마지막에서 시작하여 루프를 반복함으로써 항목이 제거 (또는 추가) 될 때 목록의 이전 항목에 영향을 미치지 않습니다. 따라서이 예제는 alist 에서조차있는 모든 항목을 올바르게 제거합니다.


반복 되는 루프에 무한 루프가 발생할 수 있는 요소를 목록에 삽입하거나 추가 할 때 비슷한 문제가 발생합니다.

alist = [0, 1, 2]
for index, value in enumerate(alist):
    # break to avoid infinite loop:
    if index == 20:     
        break           
    alist.insert(index, 'a')
print(alist)
# Out (abbreviated): ['a', 'a', ..., 'a', 'a',  0,   1,   2]

break 조건이 없으면 컴퓨터는 메모리가 부족하지 않고 프로그램을 계속 실행할 수있는 한 루프에 'a' 가 삽입됩니다. 이와 같은 상황에서는 일반적으로 새 목록을 만들고 원래 목록을 반복하면서 항목을 새 목록에 추가하는 것이 좋습니다.


for 루프 를 사용할 때 목록 요소를 자리 표시 자 변수로 수정할 수 없습니다 .

alist = [1,2,3,4]
for item in alist:
    if item % 2 == 0:
        item = 'even'
print(alist)
# Out: [1,2,3,4]

위의 예에서 item 변경해도 원래 목록의 내용은 실제로 변경되지 않습니다 . 목록 색인 ( alist[2] )을 사용해야하고, enumerate() 는 다음과 같이 잘 작동합니다.

alist = [1,2,3,4]
for index, item in enumerate(alist):
    if item % 2 == 0:
        alist[index] = 'even'
print(alist)
# Out: [1, 'even', 3, 'even']

어떤 경우에는 while 루프 가 더 나은 선택 일 수 있습니다.

목록의 모든 항목삭제하려면 다음을 수행하십시오.

zlist = [0, 1, 2]
while zlist:
    print(zlist[0])
    zlist.pop(0)
print('After: zlist =', zlist)

# Out: 0
#      1
#      2
# After: zlist = []

단순히 zlist 를 재설정 zlist 동일한 결과가 나타납니다.

zlist = []

위의 예제는 len() 과 결합하여 특정 지점 이후에 중지하거나 목록에서 x 항목을 제외한 모든 항목을 삭제할 수 있습니다.

zlist = [0, 1, 2]
x = 1
while len(zlist) > x:
    print(zlist[0])
    zlist.pop(0)
print('After: zlist =', zlist)

# Out: 0
#      1
# After: zlist = [2]

또는 특정 조건을 충족하는 요소를 삭제하는 동안 목록반복 할 수 있습니다 (이 경우 모든 짝수 요소 삭제).

zlist = [1,2,3,4,5]
i = 0
while i < len(zlist):
    if zlist[i] % 2 == 0:
        zlist.pop(i)
    else:
        i += 1
print(zlist)
# Out: [1, 3, 5]

요소를 삭제 한 후에는 i 를 증가시키지 않습니다. zlist[i] 에서 요소를 삭제하면 다음 항목의 색인이 1 씩 감소하므로 다음 반복에서 i 와 동일한 값으로 zlist[i] 를 검사하면 목록의 다음 항목을 올바르게 검사하게됩니다 .


원하지 않는 항목을 목록에서 제거하는 방법을 생각해 보면 원하는 항목을 새 목록추가 할 수 있습니다 . 다음 예제는 후자 while 루프 예제의 대안입니다.

zlist = [1,2,3,4,5]

z_temp = []
for item in zlist:
    if item % 2 != 0:
        z_temp.append(item)
zlist = z_temp
print(zlist)
# Out: [1, 3, 5]

여기서 우리는 원하는 결과를 새로운 목록에 넣고 있습니다. 그런 다음 선택적으로 임시 목록을 원래 변수에 재 할당 할 수 있습니다.

이러한 생각의 흐름으로 파이썬에서 가장 우아하고 강력한 기능 중 하나 인 필독 ( list comprehensions )을 호출 할 수 있습니다. 이는 일시적인 목록을 제거하고 이전에 논의 된 장소 / 목록 변경 돌연변이 이데올로기에서 벗어납니다.

zlist = [1,2,3,4,5]
[item for item in zlist if item % 2 != 0]
# Out: [1, 3, 5]

변경 가능한 기본 인수

def foo(li=[]):
    li.append(1)
    print(li)

foo([2])
# Out: [2, 1]
foo([3])
# Out: [3, 1]

이 코드는 예상대로 동작하지만 인수를 전달하지 않으면 어떻게됩니까?

foo()
# Out: [1] As expected...

foo()
# Out: [1, 1]  Not as expected...

이는 함수 및 메서드의 기본 인수가 런타임이 아닌 정의 시간에 평가되기 때문입니다. 그래서 우리는 li 리스트의 인스턴스를 하나만 가지고 있습니다.

이 문제를 해결하는 방법은 기본 인수에 불변 유형 만 사용하는 것입니다.

def foo(li=None):
    if not li:
        li = []
    li.append(1)
    print(li)

foo()
# Out: [1]

foo()
# Out: [1]

개선 사항이지만 if not liFalse 정확하게 평가 if not li 않더라도 0 길이 시퀀스와 같이 많은 다른 객체도 마찬가지입니다. 다음 예제 인수는 의도하지 않은 결과를 초래할 수 있습니다.

x = []
foo(li=x)
# Out: [1]

foo(li="")
# Out: [1]

foo(li=0) 
# Out: [1]

관용적 인 방법은 None 객체에 대한 인수를 직접 확인하는 것입니다.

def foo(li=None):
    if li is None:
        li = []
    li.append(1)
    print(li)

foo()
# Out: [1]

곱셈 및 공통 참조 목록 표시

다음을 곱하여 중첩 된 목록 구조를 만드는 경우를 생각해보십시오.

li = [[]] * 3
print(li)
# Out: [[], [], []]

언뜻 보면 3 개의 서로 다른 중첩 목록을 포함하는 목록이 있다고 생각할 것입니다. 첫 번째 요소에 1 을 추가하려고합니다.

li[0].append(1)
print(li)
# Out: [[1], [1], [1]]

1li 모든 목록에 추가되었습니다.

그 이유는 [[]] * 3 은 3 개의 다른 listlist 을 만들지 않기 때문입니다. 오히려, 그것은 생성 list 같은 3 참조 들고 list 개체. 따라서, li[0] 추가 할 때, 변경은 li 모든 하위 요소에서 볼 수 있습니다. 이것은 다음과 같습니다.

li = []
element = [[]]
li = element + element + element
print(li)
# Out: [[], [], []]
element.append(1)
print(li)
# Out: [[1], [1], [1]]

id 를 사용하여 포함 된 list 의 메모리 주소를 인쇄하면이 사실을 확인할 수 있습니다.

li = [[]] * 3
print([id(inner_list) for inner_list in li])
# Out: [6830760, 6830760, 6830760]

해결 방법은 루프를 사용하여 내부 목록을 만드는 것입니다.

li = [[] for _ in range(3)]

단일 list 을 작성한 후 3 개의 참조를 작성하는 대신 3 개의 서로 다른 별개 목록을 작성합니다. 이것은 id 함수를 사용하여 다시 확인할 수 있습니다.

print([id(inner_list) for inner_list in li])
# Out: [6331048, 6331528, 6331488]

당신도 이것을 할 수 있습니다. 이로 인해 각 append 호출에서 새로운 빈 목록이 작성됩니다.

>>> li = []
>>> li.append([])
>>> li.append([])
>>> li.append([])
>>> for k in li: print(id(k))
... 
4315469256
4315564552
4315564808

시퀀스를 루프하기 위해 인덱스를 사용하지 마십시오.

금지 사항 :

for i in range(len(tab)):
    print(tab[i])

해야 할 일 :

for elem in tab:
    print(elem)

for 는 대부분 반복 작업을 자동화합니다.

인덱스와 요소가 실제로 필요한 경우 열거 형을 사용하십시오 .

for i, elem in enumerate(tab):
     print((i, elem))

"=="를 사용하여 참 또는 거짓을 검사 할 때주의하십시오.

if (var == True):
    # this will execute if var is True or 1, 1.0, 1L

if (var != True):
    # this will execute if var is neither True nor 1

if (var == False):
    # this will execute if var is False or 0 (or 0.0, 0L, 0j)

if (var == None):
    # only execute if var is None

if var:
    # execute if var is a non-empty string/list/dictionary/tuple, non-0, etc

if not var:
    # execute if var is "", {}, [], (), 0, None, etc.

if var is True:
    # only execute if var is boolean True, not 1

if var is False:
    # only execute if var is boolean False, not 0

if var is None:
    # same as var == None

가능한지 확인하지 말고 그냥 수행하고 오류를 처리하십시오.

Pythonistas는 보통 "허가보다는 용서를 요구하는 것이 쉽다"고 말한다.

금지 사항 :

if os.path.isfile(file_path):
    file = open(file_path)
else:
    # do something

해야 할 것:

try:
    file = open(file_path)
except OSError as e:
    # do something

Python 2.6+ 에서는 더 좋습니다.

with open(file_path) as file:

그것은 훨씬 더 일반적이기 때문에 훨씬 더 좋습니다. 거의 모든 것에 try/except 를 적용 할 수 있습니다. 그것을 방지하기 위해해야 ​​할 일에 신경 쓰지 않아도됩니다.

유형을 확인하지 마라.

파이썬은 동적으로 타입이 지정되므로 유형을 검사하면 유연성이 떨어집니다. 대신, 동작을 확인 하여 오리 입력 을 사용하십시오. 함수에서 문자열을 예상하면 str() 을 사용하여 모든 객체를 문자열로 변환하십시오. 리스트를 원하면 list() 를 사용하여 반복 가능한 모든 것을리스트로 변환하십시오.

금지 사항 :

def foo(name):
    if isinstance(name, str):
        print(name.lower())

def bar(listing):
    if isinstance(listing, list):
        listing.extend((1, 2, 3))
        return ", ".join(listing)

해야 할 것:

def foo(name) :
    print(str(name).lower())

def bar(listing) :
    l = list(listing)
    l.extend((1, 2, 3))
    return ", ".join(l)

마지막으로 foo 는 모든 객체를 허용합니다. bar 는 문자열, 튜플, 세트,리스트 등을 받아 들일 것입니다. 저렴한 DRY.

공백과 탭을 함께 사용하지 마십시오.

개체 를 첫 번째 부모로 사용

이것은 까다 롭지 만 프로그램이 성장함에 따라 문제가됩니다. Python 2.x 에는 오래된 클래스와 새로운 클래스가 있습니다. 오래된 것들은, 음, 오래되었습니다. 그들은 몇 가지 기능이 부족하고 상속으로 어색한 행동을 할 수 있습니다. 사용할 수 있으려면 모든 수업이 "새로운 스타일"이어야합니다. 그렇게하려면 object 에서 상속 받도록하십시오.

금지 사항 :

class Father:
    pass

class Child(Father):
    pass

해야 할 것:

class Father(object):
    pass


class Child(Father):
    pass

Python 3.x 에서는 모든 클래스가 새로운 스타일이므로 그렇게 할 필요가 없습니다.

init 메소드 밖에서 클래스 속성을 초기화하지 않는다.

다른 언어를 사용하는 사람들은 자바 또는 PHP에서하는 일이기 때문에 유혹을 느끼게됩니다. 클래스 이름을 작성한 다음 속성을 나열하고 기본값을 지정합니다. 파이썬에서 작동하는 것처럼 보이지만, 생각대로 작동하지 않습니다. 그렇게하면 클래스 속성 (정적 속성)이 설정되고 객체 속성을 가져 오려고하면 비어 있지 않는 한 그 값이 제공됩니다. 이 경우 클래스 속성을 반환합니다. 그것은 두 가지 큰 위험을 의미합니다 :

  • 클래스 속성이 변경되면 초기 값이 변경됩니다.

  • 가변 객체를 기본값으로 설정하면 동일한 객체가 인스턴스간에 공유됩니다.

하지 마라 (정적이 아니라면) :

class Car(object):
    color = "red"
    wheels = [Wheel(), Wheel(), Wheel(), Wheel()]

해야 할 일 :

class Car(object):
    def __init__(self):
        self.color = "red"
        self.wheels = [Wheel(), Wheel(), Wheel(), Wheel()]

정수 및 문자열 ID

파이썬은 반복되는 생성에서 불필요한 오버 헤드를 줄이기 위해 정수 범위에 내부 캐싱을 사용합니다.

결과적으로 정수 ID를 비교할 때 혼동을 줄 수 있습니다.

>>> -8 is (-7 - 1)
False
>>> -3 is (-2 - 1)
True

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

>>> (255 + 1) is (255 + 1)
True
>>> (256 + 1) is (256 + 1)
False

무엇을 기다립니다?

동일성 연산 is 일부 정수 ( -3 , 256 )에서는 True 를 나타내지 만 일부 정수 ( -8 , 257 )에서는 그렇지 않음을 알 수 있습니다.

보다 구체적으로, [-5, 256] 범위의 정수는 인터프리터가 시작될 때 내부적으로 캐시되며 한 번만 생성됩니다. 따라서, 그들은 동일하며 자신의 정체성을 비교하는 is 산출 True ; 이 범위를 벗어나는 정수는 즉석에서 생성되며 ID는 False 와 비교됩니다.

이것이 일반적인 함정이기 때문에 이것은 일반적인 테스트 범위이기 때문에 코드가 개발 단계에서 완벽하게 작동 한 후 명백한 이유없이 후반 작업 (또는 악화) 과정에서 실패 할 때가 있습니다.

솔루션은 항등 ( == ) 연산자를 사용하고 항등 연산자 ( is )를 사용 하지 않고 항상 값을 비교하는 것 입니다.


파이썬은 일반적으로 사용되는 문자열에 대한 참조를 유지하기 때문에 문자열의 ID (예 : is 사용)를 비교할 때 유사하게 혼동을 줄 수 있습니다.

>>> 'python' is 'py' + 'thon'
True

문자열 'python' 이 일반적으로 사용되므로 파이썬에는 문자열 'python' 대한 모든 참조가 사용하는 하나의 객체가 있습니다.

흔하지 않은 문자열의 경우 문자열이 동일한 경우에도 ID 비교가 실패합니다.

>>> 'this is not a common string' is 'this is not' + ' a common string'
False
>>> 'this is not a common string' == 'this is not' + ' a common string'
True

따라서 Integer 규칙과 마찬가지로 항등 연산자 ( is ) is 아닌 항등 ( == ) 연산자를 사용하여 문자열 값을 항상 비교 하십시오.

int 리터럴 속성에 액세스

파이썬의 모든 것이 리터럴이라고해도 들었을 것입니다. 예를 들어, 7 은 객체이기도하므로 속성이 있음을 의미합니다. 예를 들어, 이러한 속성 중 하나는 bit_length 입니다. 그것은 호출 된 값을 나타내는 데 필요한 비트의 양을 리턴합니다.

x = 7
x.bit_length()
# Out: 3

위의 코드가 작동하는 것을 보면서 7.bit_length() 가 제대로 작동한다고 직관적으로 생각할 수도 있습니다. 단지 SyntaxError 가 발생한다는 것을 알기 위해서입니다. 왜? 왜냐하면 인터프리터는 속성 액세스와 부동 소수점 (예 : 7.2 또는 7.bit_length() )을 구별해야하기 때문입니다. 그렇게 할 수 없기 때문에 예외가 발생합니다.

int 리터럴 속성에 액세스하는 데는 몇 가지 방법이 있습니다.

# parenthesis
(7).bit_length()
# a space
7 .bit_length()

float 리터럴을 생성하고 floatbit_length() 메서드가 없기 때문에 두 점 (예 : 7..bit_length() )을 사용하면이 경우에는 작동하지 않습니다.

이 문제는 float 리터럴에 속성을 액세스 할 때 존재하지 않습니다. 왜냐하면 float 리터럴에 2를 포함 할 수 없다는 것을 충분히 인식 할 수있는 인터페터가 "스마트"하기 때문입니다 . 예 :

7.2.as_integer_ratio()
# Out: (8106479329266893, 1125899906842624)

체이닝 또는 오퍼레이터

몇 가지 동등한 비교를 테스트 할 때 :

if a == 3 or b == 3 or c == 3:

이것을 줄여서 유혹한다.

if a or b or c == 3: # Wrong

이것은 잘못되었습니다. or 연산자는 == 보다 낮은 우선 순위 를 가지므로 표현식은 if (a) or (b) or (c == 3): 됩니다. 올바른 방법은 명시 적으로 모든 조건을 검사하는 것입니다.

if a == 3 or b == 3 or c == 3:  # Right Way

또는 내장 된 any() 함수를 체인 or 연산자 대신 사용할 수 있습니다.

if any([a == 3, b == 3, c == 3]): # Right

또는 더 효율적으로 만들 수 있습니다.

if any(x == 3 for x in (a, b, c)): # Right

또는 짧게 만들려면 다음과 같이하십시오.

if 3 in (a, b, c): # Right

여기에서는 in 연산자를 사용하여 비교할 값이 포함 된 튜플에 값이 있는지 테스트합니다.

마찬가지로, 쓰기가 올바르지 않습니다.

if a == 1 or 2 or 3:

그것은 다음과 같이 쓰여야한다.

if a in (1, 2, 3):

sys.argv [0]은 실행중인 파일의 이름입니다.

sys.argv[0] 의 첫 번째 요소는 실행중인 파이썬 파일의 이름입니다. 나머지 요소는 스크립트 인수입니다.

# script.py
import sys

print(sys.argv[0])
print(sys.argv)

$ python script.py
=> script.py
=> ['script.py']

$ python script.py fizz
=> script.py
=> ['script.py', 'fizz']

$ python script.py fizz buzz
=> script.py
=> ['script.py', 'fizz', 'buzz']

사전은 순서가 없습니다.

예를 들어, C ++ std::map 과 같은 키를 사용하여 파이썬 사전을 정렬 할 것으로 기대할 수 있지만, 그렇지 않은 경우가 있습니다.

myDict = {'first': 1, 'second': 2, 'third': 3}
print(myDict)
# Out: {'first': 1, 'second': 2, 'third': 3}

print([k for k in myDict])
# Out: ['second', 'third', 'first']

파이썬에는 키에 의해 요소를 자동으로 정렬하는 빌트인 클래스가 없다.

그러나 정렬이 필수는 아니며 사전에 키 / 값 쌍 삽입 순서를 기억하려는 경우 collections.OrderedDict 를 사용할 수 있습니다.

from collections import OrderedDict

oDict = OrderedDict([('first', 1), ('second', 2), ('third', 3)])

print([k for k in oDict])
# Out: ['first', 'second', 'third']

표준 사전으로 OrderedDict 를 초기화해도 사전은 어떤 식 으로든 정렬되지 않습니다. 이 구조가하는 모든 작업은 키 삽입 순서를 유지 하는 것입니다.

파이썬 3.6 에서 메모리 사용을 향상시키기 위해 사전 구현이 변경되었습니다 . 이 새로운 구현의 부작용은 함수에 전달 된 키워드 인수의 순서도 유지한다는 것입니다.

파이썬 3.x 3.6
def func(**kw): print(kw.keys())

func(a=1, b=2, c=3, d=4, e=5) 
dict_keys(['a', 'b', 'c', 'd', 'e']) # expected order 

주의 사항 : " 이 새로운 구현의 순서 보존 측면은 구현 세부 사항으로 간주되므로 의존해서는 안됩니다 ."

전역 인터프리터 잠금 (GIL) 및 차단 스레드

파이썬의 길 (GIL) 에 관해 많이 쓰여졌다 . 다중 스레드 (다중 프로세스와 혼동하지 말 것) 응용 프로그램을 처리 할 때 때때로 혼란을 야기 할 수 있습니다.

다음은 그 예입니다.

import math
from threading import Thread

def calc_fact(num):
    math.factorial(num)

num = 600000
t = Thread(target=calc_fact, daemon=True, args=[num])
print("About to calculate: {}!".format(num))
t.start()
print("Calculating...")
t.join()
print("Calculated")

쓰레드가 시작된 직후에 Calculating... 출력되는 것을 볼 수있을 것입니다. 우리는 계산이 새로운 쓰레드에서 발생하기를 원합니다! 그러나 실제로는 계산이 완료된 후에 인쇄됩니다. 이는 새 스레드가 실행되는 동안 GIL을 잠글 수있는 C 함수 ( math.factorial )에 의존하기 때문입니다.

이 문제를 해결하는 데는 몇 가지 방법이 있습니다. 첫 번째는 네이티브 파이썬에서 계승 함수를 구현하는 것입니다. 이렇게하면 루프 내부에있는 동안 주 스레드가 제어 할 수 있습니다. 단점은 더 이상 C 함수를 사용하지 않기 때문에이 솔루션이 훨씬 느리다는 것입니다.

def calc_fact(num):
    """ A slow version of factorial in native Python """
    res = 1
    while num >= 1:
        res = res * num
        num -= 1
    return res

실행을 시작하기 전에 일정 시간 sleepsleep 수 있습니다. 주 : 이것은 실제로 프로그램이 C 함수 내에서 일어나는 계산을 중단시키는 것을 허용하지 않을 것이지만, 그것은 당신이 기대할 수있는 당신의 주 스레드가 스폰 이후에 계속되도록 허용 할 것입니다.

def calc_fact(num):
    sleep(0.001)
    math.factorial(num)

목록 내포 및 루프에 누출되는 변수

다음 목록 이해를 고려하십시오.

Python 2.x 2.7
i = 0
a = [i for i in range(3)]
print(i) # Outputs 2

이는 목록 이해가 루프 제어 변수를 주변 범위 ( 소스 )로 "누설"한다는 사실 때문에 파이썬 2에서만 발생합니다. 이 동작으로 인해 찾기 어려운 버그가 생길 수 있으며 Python 3에서 수정되었습니다 .

Python 3.x 3.0
i = 0
a = [i for i in range(3)]
print(i) # Outputs 0

비슷하게 for 루프는 반복 변수에 대한 사적인 범위를 가지고 있지 않다.

i = 0
for i in range(3):
    pass
print(i) # Outputs 2

이러한 유형의 동작은 Python 2와 Python 3 모두에서 발생합니다.

변수 유출로 인한 문제를 피하려면 목록 내포 및 새 루프를 적절하게 사용하십시오.

복수 반환

함수 xyz는 a와 b의 두 값을 반환합니다.

def xyz():
  return a, b

코드 호출 xyz는 결과를 하나의 변수에 저장합니다. xyz는 하나의 값만 반환한다고 가정합니다.

t = xyz()

의 값 t 실제로 튜플 (A, B) 등 모든 작업입니다 t 는 튜플은 튜플에 대한 예기치 않은 오류 코드에 깊은 실패 할 수 있습니다하지 않는 가정.

TypeError : type 튜플이 정의하지 않은 메서드입니다.

해결 방법은 다음과 같습니다.

a, b = xyz()

초보자는 튜플 오류 메시지를 읽는 것만으로이 메시지의 원인을 찾는 데 어려움을 겪을 것입니다!

파이썬 JSON 키

my_var = 'bla';
api_key = 'key';
...lots of code here...
params = {"language": "en", my_var: api_key}

JavaScript에 익숙하다면 Python 사전의 변수 평가는 기대 한 바가 아닙니다. 자바 스크립트 params 문장은 params 객체를 다음과 같이 만듭니다.

{
    "language": "en",
    "my_var": "key"
}

그러나 파이썬에서는 다음과 같은 사전을 만듭니다.

{
    "language": "en",
    "bla": "key"
}

my_var 이 평가되고 해당 값이 키로 사용됩니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow