Is Python sterk getypt?

Ik ben links tegengekomen die zeggen dat Python een sterk getypte taal is.

Ik dacht echter dat je dit in sterk getypte talen niet kon doen:

bob = 1
bob = "bob"

Ik dacht dat een sterk getypte taal het veranderen van type niet accepteerde tijdens runtime. Misschien heb ik een verkeerde (of te simplistische) definitie van sterke/zwakke types.

Dus, is Python een sterk of zwak getypte taal?


Antwoord 1, autoriteit 100%

Python is sterk, dynamisch getypt.

  • Sterktypen betekent dat het type van een waarde niet op onverwachte manieren verandert. Een string die alleen cijfers bevat, wordt niet op magische wijze een getal, zoals in Perl wel kan gebeuren. Elke verandering van type vereist een expliciete conversie.
  • Dynamischtypen betekent dat runtime-objecten (waarden) een type hebben, in tegenstelling tot statisch typen waarbij variabelen een type hebben.

Wat uw voorbeeld betreft

bob = 1
bob = "bob"

Dit werkt omdat de variabele geen type heeft; het kan elk object een naam geven. Na bob=1zul je zien dat type(bob)intretourneert, maar na bob="bob", retourneert het str. (Merk op dat typeeen reguliere functie is, dus het evalueert zijn argument en retourneert vervolgens het type van de waarde.)

Vergelijk dit met oudere dialecten van C, die zwak, statisch waren getypt, zodat pointers en gehele getallen vrijwel uitwisselbaar waren. (Moderne ISO C vereist in veel gevallen conversies, maar mijn compiler is hier standaard nog steeds mild in.)

Ik moet hieraan toevoegen dat sterk versus zwak typen meer een continuüm is dan een booleaanse keuze. C++ typt sterker dan C (meer conversies vereist), maar het typesysteem kan worden ondermijnd door pointercasts te gebruiken.

De kracht van het typesysteem in een dynamische taal zoals Python wordt echt bepaald door hoe de primitieven en bibliotheekfuncties reageren op verschillende typen. Bijvoorbeeld, +is overbelast, zodat het werkt op twee getallen oftwee strings, maar niet op een string en een getal. Dit is een ontwerpkeuze die is gemaakt toen +werd geïmplementeerd, maar niet echt een noodzaak als gevolg van de semantiek van de taal. Als je +op een aangepast type overbelast, kun je het zelfs impliciet alles naar een getal laten converteren:

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)

Instance van klasse Fookan aan andere objecten worden toegevoegd:

>>> a = Foo(42)
>>> a + "1"
43.0
>>> a + Foo
42
>>> a + 1
43.0
>>> a + None
42

Houd er rekening mee dat Python, hoewel sterk getypeerd, helemaal in orde is met het toevoegen van objecten van het type inten floaten een object van het type floatretourneert ( bijv. int(42) + float(1)geeft 43.0terug). Aan de andere kant, vanwege de mismatch tussen typen zou Haskell klagen als men het volgende probeert (42 :: Integer) + (1 :: Float). Dit maakt Haskell een strikt getypeerde taal, waar typen volledig onsamenhangend zijn en alleen een gecontroleerde vorm van overbelasting mogelijk is via typeklassen.


Antwoord 2, autoriteit 17%

Er zijn enkele belangrijke problemen die volgens mij alle bestaande antwoorden over het hoofd hebben gezien.


Zwak typen betekent toegang geven tot de onderliggende representatie. In C kan ik een aanwijzer naar karakters maken en vervolgens de compiler vertellen dat ik deze als aanwijzer naar gehele getallen wil gebruiken:

char sz[] = "abcdefg";
int *i = (int *)sz;

Op een little-endian platform met 32-bits gehele getallen, maakt dit van ieen array van de getallen 0x64636261en 0x00676665. Je kunt zelfs zelf pointers casten naar gehele getallen (van de juiste grootte):

intptr_t i = (intptr_t)&sz;

En dit betekent natuurlijk dat ik het geheugen overal in het systeem kan overschrijven.*

char *spam = (char *)0x12345678
spam[0] = 0;

* Natuurlijk gebruiken moderne besturingssystemen virtueel geheugen en paginabeveiliging, dus ik kan alleen het geheugen van mijn eigen proces overschrijven, maar er is niets aan C zelf dat zo’n bescherming biedt, zoals iedereen die ooit codeerde op bijvoorbeeld het klassieke Mac OS of Win16 kan het je vertellen.

Traditioneel Lisp stond soortgelijke soorten hacking toe; op sommige platforms waren floats met dubbele woorden en tegencellen van hetzelfde type, en je kon de ene gewoon doorgeven aan een functie die de andere verwachtte en het zou “werken”.

De meeste talen zijn tegenwoordig niet zo zwak als C en Lisp waren, maar veel van hen zijn nog steeds enigszins lekkend. Bijvoorbeeld, elke OO-taal met een niet-aangevinkt “downcast”,* dat is een typelek: je vertelt in wezen de compiler: “Ik weet dat ik je niet genoeg informatie heb gegeven om te weten dat dit veilig is, maar ik ben er vrij zeker van it is,” wanneer het hele punt van een systeemtype is dat de compiler altijd genoeg informatie heeft om te weten wat veilig is.

* Een gecontroleerde downcast maakt het typesysteem van de taal niet zwakker, alleen maar omdat het de controle naar runtime verplaatst. Als dat zo was, zou subtype-polymorfisme (ook bekend als virtuele of volledig dynamische functieaanroepen) dezelfde schending zijn van het typesysteem, en ik denk niet dat iemand dat wil zeggen.

Er zijn maar weinig “scripting”-talen die in deze zin zwak zijn. Zelfs in Perl of Tcl kun je geen string nemen en zijn bytes interpreteren als een geheel getal.* Maar het is de moeite waard om op te merken dat in CPython (en op dezelfde manier voor veel andere tolken voor veel talen), als je echt volhardend bent, je kan ctypesgebruiken om libpythonte laden, de idvan een object naar een POINTER(Py_Object)te casten en de type systeem te lekken. Of dit het typesysteem zwak maakt of niet, hangt af van uw gebruiksscenario’s – als u een in-taal beperkte uitvoeringssandbox probeert te implementeren om de veiligheid te garanderen, krijgt u te maken met dit soort ontsnappingen…

* Je kunt een functie als struct.unpackgebruiken om de bytes te lezen en een nieuwe int te bouwen van “hoe C deze bytes zou voorstellen”, maar dat is duidelijk niet lek; zelfs Haskell staat dat toe.


Ondertussen is impliciete conversie echt iets anders dan een zwak of lek systeem.

Elke taal, zelfs Haskell, heeft functies om bijvoorbeeld een geheel getal om te zetten in een string of een float. Maar sommige talen zullen sommige van die conversies automatisch voor u uitvoeren, bijvoorbeeld in C, als u een functie aanroept die een floatwil, en u geeft deze door in int, wordt voor u omgezet. Dit kan zeker leiden tot bugs met bijvoorbeeld onverwachte overflows, maar het zijn niet dezelfde bugs die je krijgt van een zwak type systeem. En C is hier niet echt zwakker; je kunt een int en een float toevoegen in Haskell, of zelfs een float samenvoegen tot een string, je moet het alleen explicieter doen.

En met dynamische talen is dit behoorlijk duister. Er bestaat niet zoiets als “een functie die wil zweven” in Python of Perl. Maar er zijn overbelaste functies die verschillende dingen doen met verschillende typen, en er is een sterk intuïtief gevoel dat, bijvoorbeeld, het toevoegen van een string aan iets anders “een functie is die een string wil”. In die zin lijken Perl, Tcl en JavaScript veel impliciete conversies uit te voeren ("a" + 1geeft u "a1"), terwijl Python veel doet minder ("a" + 1levert een uitzondering op, maar 1.0 + 1geeft je wel 2.0*). Het is gewoon moeilijk om die betekenis in formele termen om te zetten – waarom zou er geen +zijn die een string en een int nodig heeft, terwijl er duidelijk andere functies zijn, zoals indexeren, die dat wel doen?

* In moderne Python kan dat worden verklaard in termen van OO-subtypering, aangezien isinstance(2, numbers.Real)waar is. Ik denk niet dat 2een instantie is van het stringtype in Perl of JavaScript… hoewel het in Tcl dat wel is, aangezien alleseen instantie is van tekenreeks.


Ten slotte is er nog een andere, volledig orthogonale definitie van ‘sterk’ versus ‘zwak’ typen, waarbij ‘sterk’ krachtig/flexibel/expressief betekent.

Met Haskell kun je bijvoorbeeld een type definiëren dat een getal, een tekenreeks, een lijst van dit type of een kaart is van tekenreeksen naar dit type, wat een perfecte manier is om alles weer te geven dat kan worden gedecodeerd vanuit JSON. Er is geen manier om een ​​dergelijk type in Java te definiëren. Maar Java heeft tenminste parametrische (generieke) typen, dus je kunt een functie schrijven die een Lijst van T nodig heeft en weten dat de elementen van het type T zijn; andere talen, zoals het vroege Java, dwongen je om een ​​List of Object te gebruiken en downcast. Maar met Java kun je tenminste nieuwe typen maken met hun eigen methoden; C laat je alleen structuren maken. En dat had BCPL niet eens. En zo verder tot aan de montage, waar de enige typen verschillende bitlengtes zijn.

Dus in die zin is het typesysteem van Haskell sterker dan dat van moderne Java, dat sterker is dan dat van vroeger, dat sterker is dan dat van C, dat sterker is dan dat van BCPL.

Dus, waar past Python in dat spectrum? Dat is een beetje lastig. In veel gevallen kun je met duck-typen alles simuleren wat je in Haskell kunt doen, en zelfs sommige dingen die je niet kunt; Natuurlijk worden fouten tijdens runtime opgevangen in plaats van tijdens compileren, maar ze worden nog steeds opgevangen. Er zijn echter gevallen waarin eend typen niet voldoende is. In Haskell kun je bijvoorbeeld zien dat een lege lijst met ints een lijst met ints is, dus je kunt besluiten dat het verminderen van +over die lijst 0* moet opleveren; in Python is een lege lijst een lege lijst; er is geen type-informatie om u te helpen beslissen wat het verminderen van +erover zou moeten doen.

* In feite laat Haskell je dit niet doen; als je de reduce-functie aanroept die geen startwaarde aanneemt op een lege lijst, krijg je een foutmelding. Maar het typesysteem is krachtig genoeg om dit konte laten werken, en dat van Python niet.


Antwoord 3, autoriteit 11%

TLDR;

Typen met Python is Dynamisch, dus u kunt een tekenreeksvariabele veranderenin een int (in een Statischetaal kunt u dat niet)

x = 'somestring'
x = 50

Typen met Python is Sterk, dus u kunt typen niet samenvoegen:

'foo' + 3 --> TypeError: cannot concatenate 'str' and 'int' objects

In zwak getypt Javascript gebeurt dit…

'foo'+3 = 'foo3'

Betreffende Type Inferentie

Java dwingt je om je objecttypes expliciet te declareren

int x = 50;

Kotlingebruikt gevolgtrekking om te beseffen dat het een int

is

x = 50

Maar omdat beide talen statischetypen gebruiken, kan xniet worden gewijzigd vanuit een int. Geen van beide talen zou een dynamischeverandering toestaan, zoals

x = 50
x = 'now a string'

Antwoord 4, autoriteit 10%

Je verwart ‘sterk getypt’met ‘dynamisch getypt’.

Ik kan het type 1niet wijzigen door de string '12'toe te voegen, maar ik kan wel kiezen welke typen ik in een variabele opslaat en dat veranderen tijdens de uitvoering van het programma tijd.

Het tegenovergestelde van dynamische typen is statische typen; De Verklaring van variabele typen verandert niet tijdens de levensduur van een programma. Het tegenovergestelde van sterk typen is zwak typen; Het type -waarden kan veranderen tijdens de levensduur van een programma.


Antwoord 5, Autoriteit 5%

Volgens deze Wiki Python Artikel Python is zowel dynamisch als sterk getypt (geeft ook een goede uitleg).

Misschien denk je over statisch getypt talen Waar typen niet kunnen veranderen tijdens het uitvoeren van programma’s en typecontrole treedt op tijdens het compileren tijd om mogelijke fouten te detecteren.

Deze vraag kan van belang zijn: Dynamic Type Talen versus Statische Type talen en dit Wikipedia-artikel over type systemen biedt meer informatie


Antwoord 6, Autoriteit 2%

De term “sterke typen” heeft geen definitieve definitie.

Daarom is het gebruik van de term afhankelijk van wie u spreekt.

Ik beschouw geen taal, waarbij het type van een variabele niet uitdrukkelijk wordt gedeclareerd of statisch getypt om sterk te worden getypt.

Sterke typen stimuleert niet alleen de conversie (bijvoorbeeld “automatisch” automatisch “converteren van een geheel getal naar een string). Het sluit opdracht uit (d.w.z. het type van een variabele te veranderen).

Als de volgende codecompulies (interpretaties), is de taal niet sterk getypt:

foo = 1
Foo = “1”

In een sterk getypte taal kan een programmeur “rekenen op” een type.

Als een programmeur bijvoorbeeld de aangifte ziet,

uint64 kzarkcount;

En hij of zij weet dat 20 regels later nog steeds een Uint64 (zolang het in hetzelfde blok gebeurt) – zonder tussenliggende code te onderzoeken.


Antwoord 7, Autoriteit 2%

Het is al een paar keer beantwoord, maar Python is een sterk getypte taal:

>>> 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'

Het volgende in JavaScript:

var x = 3    
var y = '4'
alert(x + y) //Produces "34"

Dat is het verschil tussen zwakke typen en sterk typen. Zwakke typen proberen automatisch van het ene type naar de andere te zetten, afhankelijk van de context (bijvoorbeeld PERL). Sterke types NOOIT Converteer impliciet.

Uw verwarring ligt in een misverstanden van hoe Python waarden bindt aan namen (gewoonlijk genoemd variabelen).

In Python hebben namen geen typen, zodat u dingen kunt doen zoals:

bob = 1
bob = "bob"
bob = "An Ex-Parrot!"

en namen kunnen worden gebonden aan alles:

>>> def spam():
...     print("Spam, spam, spam, spam")
...
>>> spam_on_eggs = spam
>>> spam_on_eggs()
Spam, spam, spam, spam

Voor verder lezen:

https://en.wikipedia.org/wiki/dynamic_dispatch

en de enigszins verwante maar geavanceerdere:

http://effbot.org/zone/call-by-Object.htm


Antwoord 8, Autoriteit 2%

Een python-variabele slaat een niet-gevetterde verwijzing op naar het doelobject dat de waarde vertegenwoordigt.

Elke opdrachtbewerking betekent het toewijzen van de niet-toegestane verwijzing naar het toegewezen object – d.w.z. het object wordt gedeeld via de originele en de nieuwe (getelde) referenties.

Het waardetype is gebonden aan het doelobject, niet aan de referentiewaarde. De (sterke) typecontrole wordt uitgevoerd wanneer een bewerking met de waarde wordt uitgevoerd (runtime).

Met andere woorden, variabelen hebben (technisch gezien) geen type — het heeft geen zin om in termen van een variabel type te denken als je precies wilt zijn. Maar verwijzingen worden automatisch verwijderd en we denken eigenlijk in termen van het type doelobject.


Antwoord 9

Ik heb zojuist een uitstekende, beknopte manier ontdekt om het te onthouden:

Dynamische/statische getypeerde expressie; sterk/zwak getypte waarde.


Antwoord 10

Ik denk dat je met dit eenvoudige voorbeeld de verschillen tussen sterk en dynamisch typen moet uitleggen:

>>> tup = ('1', 1, .1)
>>> for item in tup:
...     type(item)
...
<type 'str'>
<type 'int'>
<type 'float'>
>>>

java:

public static void main(String[] args) {
        int i = 1;
        i = "1"; //will be error
        i = '0.1'; // will be error
    }

Antwoord 11

De bestaande antwoorden zijn het er grotendeels over eens dat Python een sterk getypeerde taal is omdat het niet impliciet waarden van het ene type naar het andere converteert. Die antwoorden vermelden het geval van het toevoegen van een string aan een geheel getal om deze bewering te ondersteunen; "foo" + 3roept een TypeErrorop in Python, terwijl in Javascript(algemeen beschouwd als een zwak getypte taal), wordt het getal 3impliciet geconverteerd naar een tekenreeks en vervolgens aaneengeschakeld, dus het resultaat is de tekenreeks "foo3".

Maar er zijn enkele andere situaties waarin Python impliciete typeconversies doet:

# implicit conversion from int to float
1 + 1.0
# implicit conversion from list to bool
if []: pass

Ter vergelijking: F#(over het algemeen beschouwd als een sterk getypeerde taal ) staat beide niet toe:

 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  

Er is dus echt geen strikte tweedeling tussen “sterk getypeerde” en “zwak getypeerde” talen, we kunnen eerder zeggen dat Python sterker getypeerd is dan Javascript, maar niet zo sterk getypeerd als F#.

p>


Antwoord 12

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....

Het bovenstaande zou gedurende een lange periode een nachtmerrie van onhoudbare code in een groot systeem creëren. Noem het wat je wilt, maar de mogelijkheid om een ​​variabele type “dynamisch” te veranderen is gewoon een slecht idee…

Other episodes