Python은 강한 타입입니까?
Python이 강력한 언어라는 링크를 우연히 발견했습니다.
다만, 타이핑이 강한 언어에서는, 이것을 할 수 없다고 생각했습니다.
bob = 1
bob = "bob"
활자가 강한 언어는 런타임에 활자 변경을 허용하지 않는 줄 알았어요.아마도 내가 강한 타입과 약한 타입을 잘못(또는 너무 단순하게) 정의하고 있는 것 같다.
그렇다면 Python은 강하거나 약하게 타이핑된 언어일까요?
Python은 강하고 역동적인 타입입니다.
- 강력한 입력은 값의 유형이 예기치 않은 방식으로 변경되지 않음을 의미합니다.숫자만 포함하는 문자열은 Perl에서 발생하는 것처럼 마법처럼 숫자가 되지 않습니다.유형을 변경할 때마다 명시적인 변환이 필요합니다.
- 동적 입력이란 변수가 유형을 갖는 정적 입력이 아니라 런타임 개체(값)에 유형이 있음을 의미합니다.
당신의 예에 대해서
bob = 1
bob = "bob"
이것은 변수에 유형이 없기 때문에 작동하며 임의의 개체에 이름을 지정할 수 있습니다.끝나고bob=1
, 당신은 그것을 발견하게 될 것이다.type(bob)
돌아온다int
단, 그 후bob="bob"
, 반환됩니다.str
(주의:type
는 정규 함수이므로 인수를 평가한 후 값의 유형을 반환합니다.)
이것을 약하고 정적으로 입력된 C의 오래된 방언과 대조하여 포인터와 정수는 거의 호환성이 있습니다.(현대 ISO C는 많은 경우 변환이 필요하지만 컴파일러는 기본적으로 이 점에 대해 관대합니다.)
강한 타이핑과 약한 타이핑은 부울 선택이라기 보다는 연속체라고 덧붙여야겠습니다.C++는 C보다 입력이 강하지만(더 많은 변환이 필요), 포인터 캐스트를 사용하여 입력 시스템을 전복시킬 수 있습니다.
Python과 같은 동적 언어에서 유형 시스템의 강도는 기본 요소와 라이브러리 함수가 다른 유형에 어떻게 반응하는지에 따라 결정됩니다.예.,+
는 오버로드되어 있기 때문에 2개의 번호 또는2개의 문자열로 동작하지만 문자열과 번호는 동작하지 않습니다.이것은, 다음의 경우에 행해지는 설계상의 선택입니다.+
구현되었지만 언어의 의미론상 꼭 필요한 것은 아닙니다.사실, 당신이 과부하일단+
커스텀 타입에서는, 모든 것을 수치로 암묵적으로 변환할 수 있습니다.
def to_number(x):
"""Try to convert function argument to float-type object."""
try:
return float(x)
except (TypeError, ValueError):
return 0
class Foo:
def __init__(self, number):
self.number = number
def __add__(self, other):
return self.number + to_number(other)
클래스의 인스턴스Foo
를 다른 오브젝트에 추가할 수 있습니다.
>>> a = Foo(42)
>>> a + "1"
43.0
>>> a + Foo
42
>>> a + 1
43.0
>>> a + None
42
강한 타입의 Python이 타입의 오브젝트를 추가하는 것은 전혀 문제가 없다는 것을 주의해 주십시오.int
그리고.float
유형 개체를 반환합니다.float
(예:int(42) + float(1)
돌아온다43.0
한편, 타입이 일치하지 않기 때문에, Haskell은 다음의 조작을 시도하면 불만을 제기합니다.(42 :: Integer) + (1 :: Float)
이로 인해 Haskell은 엄격하게 입력된 언어로, 타입은 완전히 분리되며 타입 클래스를 통해 제어된 형태의 오버로드만 가능합니다.
기존 답변이 모두 놓쳤다고 생각하는 몇 가지 중요한 문제가 있습니다.
약한 타이핑은 기본 표현에 대한 액세스를 허용하는 것을 의미합니다.C에서는 문자에 대한 포인터를 작성하고, 그것을 정수에 대한 포인터로 사용하고 싶다고 컴파일러에게 말할 수 있습니다.
char sz[] = "abcdefg";
int *i = (int *)sz;
32비트 정수를 사용하는 리틀 엔디안 플랫폼에서는i
그 숫자의 배열로0x64636261
그리고.0x00676665
실제로 (적절한 크기의) 정수에 포인터 자체를 캐스팅할 수도 있습니다.
intptr_t i = (intptr_t)&sz;
물론 시스템 내 어디에서나 메모리를 덮어쓸 수 있습니다.*
char *spam = (char *)0x12345678
spam[0] = 0;
* 물론 최신 OS는 가상 메모리와 페이지 보호를 사용하기 때문에 프로세스 메모리만 덮어쓸 수 있지만 C 자체에 대해 Classic Mac OS나 Win16을 코드화한 적이 있는 사람이라면 누구나 알 수 있는 보호 기능이 없습니다.
기존의 Lisp에서는 유사한 종류의 해킹이 가능했습니다.일부 플랫폼에서는 이중 워드 플로트와 콘셀이 같은 타입으로 되어 있었습니다.또, 한쪽을 다른 한쪽을 다른쪽을 기대하는 함수에 건네주면, 「작동」
오늘날 대부분의 언어는 C나 Lisp처럼 약하지는 않지만, 여전히 많은 언어가 유출되어 있다.예를 들어, 체크되지 않은 "다운캐스트"가 있는 OO 언어*는 타입 리크입니다.타입 시스템의 요점은 컴파일러가 항상 어떤 것이 안전한지 알 수 있을 만큼 충분한 정보를 주지 않았다는 것입니다.
* 체크 다운캐스트가 실행 시로 이동한다고 해서 언어의 타입 시스템이 약해지는 것은 아닙니다.그렇다면 서브타입의 다형성(가상 또는 완전 다이내믹 함수 호출)은 타입 시스템을 위반하는 것과 같기 때문에 아무도 그렇게 말하고 싶지 않다고 생각합니다.
이런 의미에서 약한 '스크립트' 언어는 거의 없습니다.Perl이나 Tcl에서도 문자열을 사용할 수 없고 바이트만 정수로 해석할 수 있습니다.* 단, CPython(및 마찬가지로 여러 언어의 다른 많은 인터프리터도 마찬가지)에서 당신이 정말로 끈질긴다면ctypes
짐을 싣다libpython
, 오브젝트의 캐스트id
에 대해서POINTER(Py_Object)
타입 시스템이 강제로 누출되도록 합니다.이로 인해 유형 시스템이 취약해질지 여부는 사용 사례에 따라 달라집니다. 보안을 확보하기 위해 언어 제한 실행 샌드박스를 구현하려면 이러한 종류의 탈출에 대처해야 합니다.
* 다음과 같은 기능을 사용할 수 있습니다.struct.unpack
"C가 이 바이트들을 어떻게 나타내는지"에서 바이트를 읽고 새로운 int를 구축합니다만, 그것은 분명히 누출이 아닙니다. Haskell조차도 그것을 허용합니다.
한편, 암묵적인 변환은 약하거나 누출이 있는 시스템과는 정말로 다른 것입니다.
모든 언어, 심지어 Haskell은 정수를 문자열이나 플로트로 변환하는 기능을 가지고 있습니다.그러나 일부 언어에서는 이러한 변환 중 일부를 자동으로 수행합니다. 예를 들어, C에서, 예를 들어 사용자가 원하는 함수를 호출하는 경우float
, 그리고 당신이 그것을 전달합니다.int
변환됩니다.이것은 예기치 않은 오버플로 등의 버그를 일으킬 수 있지만, 약한 타입의 시스템에서 발생하는 버그와는 다릅니다.여기서 C는 더 약하지 않습니다. Haskell에서 int와 float를 추가하거나 float를 문자열에 연결할 수 있습니다. 더 명확하게 해야 합니다.
역동적인 언어에서는, 이것은 꽤 애매합니다.Python이나 Perl에는 "flot을 원하는 함수"라는 것이 없습니다.그러나 다른 유형의 다른 작업을 수행하는 오버로드된 함수가 있으며, 예를 들어 문자열을 다른 항목에 추가하는 것은 "열을 원하는 함수"라는 직관적인 느낌이 강합니다.그런 의미에서 Perl, Tcl 및 JavaScript는 많은 암묵적인 변환을 수행하는 것으로 보입니다."a" + 1
주다"a1"
Python은 훨씬 적은 작업("a" + 1
예외는 있지만1.0 + 1
를 제공합니까?2.0
*) 이 의미를 공식 용어로 표현하기가 어려울 뿐인데, 왜 이 기능을 사용하면 안 되는가?+
문자열과 int를 필요로 하는 경우 인덱싱과 같은 다른 기능이 필요한 경우?
* 사실 현대의 Python에서는 OO 서브타이핑으로 설명할 수 있습니다.isinstance(2, numbers.Real)
정말이에요.제 생각에 이 모든 것이 다 그런 의미라고는 생각되지 않습니다.2
는 Perl 또는 JavaScript의 문자열 유형 인스턴스입니다.단, TCL에서는 모든 것이 문자열 인스턴스이기 때문에 실제로는 그렇습니다.
마지막으로, 완전히 직교하는 또 다른 "강력한" 대"weak" 타이핑입니다.여기서 "strong"은 강력한/강력한/적극적인 것을 의미합니다.
예를 들어 Haskell을 사용하면 숫자, 문자열, 이 유형의 목록 또는 문자열에서 이 유형의 맵을 정의할 수 있습니다. 이는 JSON에서 디코딩할 수 있는 모든 유형을 완벽하게 나타내는 방법입니다.Java에서는 이러한 유형을 정의할 방법이 없습니다.그러나 적어도 Java에는 파라미터(일반) 타입이 있기 때문에 T의 리스트를 가져와서 요소가 T형임을 알 수 있는 함수를 작성할 수 있습니다.초기 Java와 같은 다른 언어에서는 오브젝트 리스트와 다운캐스트를 사용해야 했습니다.그러나 적어도 Java에서는 독자적인 방법으로 새로운 유형을 작성할 수 있습니다.C에서는 구조체만 작성할 수 있습니다.그리고 BCPL은 그것조차 가지고 있지 않았다.다음으로 어셈블리까지 이어집니다.여기서는 비트 길이가 다른 타입은 다릅니다.
그런 의미에서 Haskell의 활자 시스템은 현대의 Java보다 더 강력하며, 이전 Java보다 더 강력하며, C보다 더 강력하며, BCPL보다 더 강력합니다.
그렇다면, Python은 이 분야에서 어디에 적합할까요?그건 좀 까다롭네요.대부분의 경우 duck typing을 사용하면 Haskell에서 할 수 있는 모든 것을 시뮬레이트할 수 있습니다.또, 에러는 컴파일 시간이 아닌 런타임에 검출되지만, 아직 검출되지 않습니다.하지만, 오리 타이핑이 충분하지 않은 경우도 있습니다.예를 들어, Haskell에서는 빈 int 목록이 int 목록임을 알 수 있기 때문에 이를 줄일 수 있습니다.+
Python 에서는 빈 리스트는 빈 리스트이며, 무엇을 줄이는지를 결정하는 데 도움이 되는 타입 정보는 없습니다.+
그래야 할 것 같아요.
* 실제로 Haskell에서는 이 작업을 수행할 수 없습니다.빈 목록에서 시작 값을 받지 않는 축소 함수를 호출하면 오류가 발생합니다.하지만 그 타입의 시스템은 충분히 강력해서 당신은 이것을 할 수 있지만, Python은 할 수 없다.
TLDR;
Python 타이핑은 Dynamic이므로 문자열 변수를 int로 변경할 수 있습니다(Static 언어에서는 변경할 수 없습니다).
x = 'somestring'
x = 50
Python 타이핑은 강력하므로 유형을 병합할 수 없습니다.
'foo' + 3 --> TypeError: cannot concatenate 'str' and 'int' objects
약하게 입력된 Javascript에서는 이러한 현상이 발생합니다.
'foo'+3 = 'foo3'
유형 추론에 대해서
Java와 같은 일부 언어에서는 개체 유형을 명시적으로 선언해야 합니다.
int x = 50;
코틀린과 같은 다른 사람들은 단순히 추측하는데int
가치 자체에서
x = 50
하지만 두 언어 모두 정적 유형을 사용하기 때문에x
에서 변경할 수 없다int
. 어느 언어도 다음과 같은 동적 변화를 허용하지 않습니다.
x = 50
x = 'now a string'
당신은 'strong type'과 'dynamic type'을 혼동하고 있다.
의 유형을 변경할 수 없습니다.1
문자열을 추가함으로써'12'
그러나 변수에 저장할 유형을 선택하고 프로그램 실행 중에 변경할 수 있습니다.
동적 입력의 반대는 정적 입력입니다. 변수 유형의 선언은 프로그램의 수명 동안 변경되지 않습니다.강력한 타이핑의 반대는 약한 타이핑입니다. 프로그램의 수명 동안 값의 유형이 변경될 수 있습니다.
이 Wiki Python 기사에 따르면 Python은 역동적이고 강하게 타이핑되어 있다(좋은 설명을 제공한다).
프로그램 실행 중에 유형을 변경할 수 없고 가능한 오류를 감지하기 위해 컴파일 시간 중에 유형 검사가 발생하는 정적 유형의 언어에 대해 생각할 수 있습니다.
SO에 관한 질문은 다음과 같습니다.동적 유형 언어 vs 정적 유형 언어 및 이 Wikipedia 문서에서는 Type Systems에 대해 자세히 설명합니다.
"strong typing"이라는 용어는 명확한 정의를 가지고 있지 않습니다.
그렇기 때문에 이 용어의 사용은 여러분이 누구와 이야기하느냐에 따라 달라집니다.
변수 유형이 명시적으로 선언되지 않았거나 정적으로 강하게 입력되지 않은 언어는 고려하지 않습니다.
강력한 타이핑은 변환(예를 들어 "자동"으로 정수에서 문자열로 변환)을 배제하지 않습니다.이는 할당(즉, 변수 유형 변경)을 금지합니다.
다음 코드가 컴파일(인터프리터)되는 경우 언어는 strong-type이 아닙니다.
Foo = 1 Foo = "1"
강한 타입의 언어에서는 프로그래머가 타입을 「기대」할 수 있습니다.
예를 들어 프로그래머가 선언문을 보면
UINT64 kZark Count;
20줄 후에도 kZarkCount는 UINT64(같은 블록에서 발생하는 한)라는 것을 알 수 있습니다.간섭 코드를 조사할 필요가 없습니다.
이미 여러 번 답변이 있었지만 Python은 강력한 타입의 언어입니다.
>>> x = 3
>>> y = '4'
>>> print(x+y)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
JavaScript의 내용은 다음과 같습니다.
var x = 3
var y = '4'
alert(x + y) //Produces "34"
그것이 약한 타이핑과 강한 타이핑의 차이점이다.약한 유형은 컨텍스트(예: Perl)에 따라 한 유형에서 다른 유형으로 자동 변환을 시도합니다.강력한 유형은 암묵적으로 변환되지 않습니다.
Python이 값을 이름에 바인딩하는 방법에 대한 오해(일반적으로 변수)가 있습니다.
Python에서는 이름에 유형이 없기 때문에 다음과 같은 작업을 수행할 수 있습니다.
bob = 1
bob = "bob"
bob = "An Ex-Parrot!"
그리고 이름은 모든 것에 구속될 수 있습니다.
>>> def spam():
... print("Spam, spam, spam, spam")
...
>>> spam_on_eggs = spam
>>> spam_on_eggs()
Spam, spam, spam, spam
자세한 내용은 다음을 참조하십시오.
https://en.wikipedia.org/wiki/Dynamic_dispatch
그리고 약간 관련이 있지만 더 고급화된 것은 다음과 같습니다.
http://effbot.org/zone/call-by-object.htm
Python 변수는 값을 나타내는 대상 개체에 대한 유형 없는 참조를 저장합니다.
모든 할당 조작은 할당된 오브젝트에 미입력 참조를 할당하는 것을 의미합니다.즉, 오브젝트는 원래 참조와 새로운 (카운트된) 참조를 통해 공유됩니다.
값 유형은 참조 값이 아닌 대상 개체에 바인딩됩니다.(strong) 타입 체크는 이 값을 사용한 조작이 실행되었을 때 실행됩니다(실행 시간).
즉, 변수(기술적으로)에는 유형이 없습니다.정확하게 하려면 변수 유형으로 생각하는 것은 의미가 없습니다.그러나 참조는 자동으로 참조되지 않고 대상 객체의 유형으로 간주됩니다.
나는 방금 그것을 외울 수 있는 아주 간결한 방법을 발견했다.
동적/정적 형식 표현식, 강력/약하게 형식화된 값입니다.
Python은 체크되지 않은 동적 유형 오류가 없기 때문에 강력한 유형입니다.즉, 타입 시스템을 위반할 수 없습니다.
정의들
- 유형: 값 집합.값의 의도된 사용(동작)을 부분적으로 정의합니다.열거형 확장자로 지정하거나 술어와 함께 지정할 수 있습니다.
- Type system: 시스템이 값이 의도한 대로 사용되었는지 확인하여 정의되지 않은 동작을 부분적으로 방지합니다.정의되지 않은 동작은 지연된 프로그램 크래시 또는 자동 데이터 손실 및 잘못된 결과 생성으로 이어질 수 있으므로 피해야 합니다.
- 유형 언어: 유형 시스템을 사용하는 언어입니다.
- 유형 오류: 유형 시스템에서 프로그램 오류를 확인할 수 있습니다.
- 식: 값을 나타내는 프로그램 텍스트.
- 정적/동적 유형: 식의 컴파일 시간/실행 시간 유형.표현식의 런타임 유형은 해당 표현식이 나타내는 값의 유형입니다.
- 정적/동적 유형 시스템: 정적/동적 유형을 확인하는 시스템 유형.
- 정적/동적 유형 언어: 정적/동적 유형 시스템을 갖춘 언어.
- 정적/동적 유형 오류: 정적/동적 유형 시스템에서 프로그램 오류를 확인할 수 있습니다.
- 약하거나 강력한 형식 언어: 선택되지 않은 동적 형식 오류가 있는 언어입니다.static type, dynamic type 또는 둘 다 strong type을 의미합니다.
- 단형식/다형식: 단일 동적 유형/복수의 동적 유형을 가진 식입니다.단형식은 하나의 의도된 용도를 가지며, 다형식은 여러 의도된 용도를 가진다.
- 범용/애드혹 다형식: 실제/가상 다형식.실제 다형식은 여러 유형을 가진 단일 값을 나타내며 가상 다형식은 단일 유형을 가진 여러 값을 나타냅니다.
- 매개 변수/포함 다형식: 유형의 일반 유형/하위 유형에 기반한 범용 다형식(예: C++ 식)
&
싱글을 나타냅니다.T* (T&)
연산자 값 여기서T
는 범용 타입/C++ 식입니다.std::exception
싱글을 나타냅니다.S
클래스 값, 여기서S
의 일반적인 서브타입입니다.std::exception
). - 오버로드/공용 다형식: 식/값 변환에 기반한 임시 다형식(예: C++ 식)
+
나타나다int (int&, int&)
그리고.float (float&, float&)
연산자 값/C++ 식3.5
나타나다float
그리고.bool
값)을 참조해 주세요.
언급
Cardelli(루카), Wegner(피터), '유형, 데이터 추상화 및 다형성의 이해', 컴퓨터 조사, 제17권, 제4, 1985, 페이지 471-523, DOI: https://doi.org/10.1145/6041.6042
이 간단한 예는 강력한 타이핑과 동적 타이핑의 차이를 설명해야 한다고 생각합니다.
>>> tup = ('1', 1, .1)
>>> for item in tup:
... type(item)
...
<type 'str'>
<type 'int'>
<type 'float'>
>>>
자바:
public static void main(String[] args) {
int i = 1;
i = "1"; //will be error
i = '0.1'; // will be error
}
기존 답변들은 Python이 어떤 유형에서 다른 유형으로 값을 암묵적으로 변환하지 않기 때문에 Python이 강력한 유형의 언어라는 것에 대부분 동의한다.이들 답변은 이 주장을 뒷받침하기 위해 정수에 문자열을 추가하는 경우를 언급하고 있다."foo" + 3
를 올리다TypeError
반면 Python에서는 Javascript(일반적으로 약하게 입력된 언어라고 생각됨)에서 숫자는3
암묵적으로 문자열로 변환된 후 연결되기 때문에 결과는 문자열입니다."foo3"
.
그러나 Python이 암묵적인 유형 변환을 수행하는 다른 상황도 있습니다.
# implicit conversion from int to float
1 + 1.0
# implicit conversion from list to bool
if []: pass
이에 비해 F#(일반적으로 강한 타입의 언어라고 생각됨)은 다음 두 가지를 모두 허용하지 않습니다.
1 + 1.0;;
----^^^
error FS0001: The type 'float' does not match the type 'int'
if [] then 1 else 2;;
---^^
error FS0001: This expression was expected to have type bool but here has type 'a list
따라서 "강하게 타이핑된" 언어와 "약하게 타이핑된" 언어라는 엄밀한 이분법이 있는 것이 아니라, Python이 Javascript보다 더 강하게 타이핑된 것이라고 말할 수 있지만 F#만큼 강하게 타이핑된 언어는 아닙니다.
class testme(object):
''' A test object '''
def __init__(self):
self.y = 0
def f(aTestMe1, aTestMe2):
return aTestMe1.y + aTestMe2.y
c = testme #get a variable to the class
c.x = 10 #add an attribute x inital value 10
c.y = 4 #change the default attribute value of y to 4
t = testme() # declare t to be an instance object of testme
r = testme() # declare r to be an instance object of testme
t.y = 6 # set t.y to a number
r.y = 7 # set r.y to a number
print(f(r,t)) # call function designed to operate on testme objects
r.y = "I am r.y" # redefine r.y to be a string
print(f(r,t)) #POW!!!! not good....
이 경우 대규모 시스템에서 장기간 유지보수가 불가능한 코드가 발생할 수 있습니다.원하는 대로 불러도 변수 유형을 동적으로 변경할 수 있는 기능은 좋지 않은 아이디어입니다.
언급URL : https://stackoverflow.com/questions/11328920/is-python-strongly-typed
'programing' 카테고리의 다른 글
array_module을 객체에 적용하시겠습니까? (0) | 2022.11.07 |
---|---|
1부터 시작하는 인덱스를 사용하여 PHP에서 어레이를 다시 인덱싱하려면 어떻게 해야 합니까? (0) | 2022.11.07 |
Eclipse에서 테스트하는 동안 -D 시스템 속성을 통과하려면 어떻게 해야 합니까? (0) | 2022.11.06 |
Android 목록 기본 설정: 요약을 선택한 값으로 지정하시겠습니까? (0) | 2022.11.06 |
PHP의 특징 – 실제 사례/베스트 프랙티스가 있습니까? (0) | 2022.11.06 |