[python] Referencia

balky vbalko na gmail.com
Pátek Únor 3 12:42:55 CET 2006


Vdaka za naozaj rozsiahle a zhrnujuce vysvetlenie - mozno by sa mohlo 
hodit na wiki.

Ale problem ostal nevyrieseny. Ako viem zabezpecit aby sa B stale 
odkazovalo na objekt s menom A. Konkretne ide o to, ze v pythone je 
cyklus for neunosne pomaly. Pracujem s NumPy a potrebujem vynulovat 
vsetky prvky pola. Je OVELA rychlejsie urobit

A = numpy.zeros(rozmer)

ako

for i in xrange(rozmer):
  A[i] = 0

Popritom vsak mam "odkazy" na pole A.

Cize este raz chcem aby sa B odkazovalo aj na nove pole s menom A. Da sa 
to v pythone vyriesit?

balky

Petr Prikryl wrote:

>Zkusím to celé shrnout a vysvětlit po svém...
>
>balky napsal:
>  
>
>>[...] pokial viem, tak ak do premennej priradim nieco,
>>nepriradil som vlastne obsah tej premennej, ale iba
>>odkaz (pointer) na ten objekt.
>>
>>    
>>
>>>>>a = [1,2,3]
>>>>>b = a
>>>>>print b
>>>>>          
>>>>>
>>[1,2,3]
>>    
>>
>>>>>a = [3,3,3]
>>>>>print a
>>>>>          
>>>>>
>>[3,3,3]
>>    
>>
>>>>>print b
>>>>>          
>>>>>
>>[1,2,3]
>>
>>Ako zabezpecim, aby sa pri zmene hodnoty a zmenila aj
>>hodnota v b? Nie je b iba odkaz na a? Alebo je to
>>odkaz na ine a?
>>    
>>
>
>JP reagoval:
>  
>
>>zapomen na to, co znas z Pascalu, C apod. Neexistuji
>>zadne promenne 'a' a 'b'. Jsou to jenom dve jmena,
>>kterym je prirazeny objekt. Kdyz napises b = a, tak
>>obe dve jmena ukazuji na stejny objekt a jakmile
>>napises a = [3,3,3], tak uz a neodkazuje na puvodni
>>objekt, zatimco b ano.
>>    
>>
>
>Je to tak trochu napůl. V Pascalu i v C++ (a myslím, že
>i v novější normě C) existuje něco, čemu se říká
>reference. V Pascalu ji najdeme jen v podobě parametru
>procedury/funkce předávaného odkazem (var). V C++ jde o
>jeden ze základních typů a při použití se chová podobně
>jako v Pythonu. Reference se od ukazatele (pointeru)
>liší tím, že se při použití jména provádí automatická
>dereference. Referenci se kromě toho nedá přiřadit něco
>jako prázdný odkaz (nelze simulovat NULL pointer).
>Použití jména proměnné typu reference se tedy jeví jako
>kdybychom přejmenovali původní objekt.
>
>V Pascalu, C/C++ a v jiných kompilovaných jazycích ale
>jméno původního objektu může vystupovat i jinak, než v
>Pythonu a podobných jazycích. Může být při překladu
>nahrazeno přímou adresou umístění objektu. Narozdíl od
>reference (a od ukazatele) takové jméno není spojeno s
>přidělením dalšího paměťového prostoru za běhu
>aplikace.
>
>V Pythonu se v podstatě pracuje jen s referencemi.
>Paměťový prostor, který za běhu programu zabírají, se
>nachází v systémovém slovníku v podobě zachycení vztahu
>'jméno': 'odkaz na objekt').
>
>
>Yeti poznamenal:
>  
>
>>[...] Kdyby se přiřazení v Pythonu říkalo pojmenování,
>>asi by se mnohé vyjasnilo.
>>
>>    
>>
>>>>>a = [1,2,3]
>>>>>b = a
>>>>>print b
>>>>>          
>>>>>
>>[1,2,3]
>>    
>>
>>>>>a = [3,3,3]
>>>>>          
>>>>>
>>Tento řádek vytvoří nový objekt [3,3,3] a pojmenuje ho
>>a. Na objekt [1,2,3] už pak existuje jen odkaz jménem
>>b. [...] b není odkaz na žádné a; jména a a b jsou dvě
>>jména téhož objektu (resp. byla, než jsi jménem a
>>pojmenoval jiný objekt).
>>
>>Nevím, čeho se přesně snažíš dosáhnout, ale zkus se
>>prostě podívat na přiřazení jako na pojmenování.
>>    
>>
>
>Python vazbě mezi jménem a objektem skutečně říká
>"vazba" (binding). O přiřazení objektu jménu říká, že
>jde o vytvoření vazby mezi jménem a objektem. V
>kompilovaných jazycích se tomu říká reference, ale
>Python je speciální v tom, že všechny reference
>uchovává v systémových slovnících (globálním a
>lokálních), kde jméno vystupuje jako klíč k hodnotě
>reference.
>
>Pro příchozí ze světa staticky kompilovaných jazyků by
>se mnohé vyjasnilo spíš tím, kdyby ony jazyky běžně
>pracovaly s pojmem reference (jako C++). Yetiho další
>poznámku bych pak mohl pro ekvivalent v kompilovaných
>jazycích přeformulovat takto:
>
>   Tento řádek vytvoří nový objekt [3,3,3] a referenci
>   přiřadí do proměnné a. Tím se původní reference na
>   objekt [1,2,3] přepíše novou hodnotou. Na původní
>   objekt [1,2,3] se pak dostaneme jen přes referenci
>   b. [...] b není reference na (refernci) a; a i b
>   jsou zpočátku dvě reference na tentýž objekt
>   seznamu.
>
>
>Jirka Vít šikovně navedl na použití zabudované funkce
>id(), která v současných implementacích Pythonu vrací
>adresu skutečného umístění objektu:
>
>  
>
>>>>>a=[1,2,3]
>>>>>b = a
>>>>>id(a)
>>>>>          
>>>>>
>>9596640
>>    
>>
>>>>>id(b)
>>>>>          
>>>>>
>>9596640
>>    
>>
>
>Snad by pro pochopení pomohlo, kdyby se přiřazení
>objektu [3, 3, 3] provedlo na dva kroky. Nejdříve jej
>pojmenujeme c (pythonovský ekvivalent přiřazení
>reference) a pak hodnotě b přiřadíme hodnotu c. Můžeme
>uvažovat, že jména jsou "proměnné v Pascalovském
>smyslu", kterým přiřazujeme hodnoty identifikací 
>skutečných objektů a při použití jmen se provádí
>automatické zpřístupnění těchto objektů:
>
>  
>
>>>>a = [1, 2, 3]
>>>>id(a)
>>>>        
>>>>
>9592464
>  
>
>>>>b = a
>>>>id(b)
>>>>        
>>>>
>9592464
>  
>
>>>>c = [3, 3, 3]
>>>>id(c)
>>>>        
>>>>
>9591744
>  
>
>>>>b = c
>>>>id(b)
>>>>        
>>>>
>9591744
>
>Tomáš Fujtalar správně poznamenal, že
>
>  
>
>>Ve Vasem pripade jste ale do a priradil novy objekt,
>>o cemz zakonite objekt b "nema paru".
>>    
>>
>
>a přidal...
>  
>
>>nebo muzete obsah celeho seznamu a prepsat novym:
>>    
>>
>>>>>a[:] = [4,5,6,7]
>>>>>print b
>>>>>          
>>>>>
>>[4,5,6,7]
>>    
>>
>
>Stejný obrat použil i Jan Martínek a píše:
>  
>
>>a nadále platí, že id(a) == id(b)
>>    
>>
> 
>Tenhle obrat je trochu "na bednu", protože jeho
>fungování je v referenční příručce (6.3 Assignment
>statements) popsán trochu komplikovaně (ono to asi
>jednodušeji popsat nejde):
>
>    If the target is a slicing: The primary expression
>    in the reference is evaluated. It should yield a
>    mutable sequence object (such as a list). The
>    assigned object should be a sequence object of the
>    same type. Next, the lower and upper bound
>    expressions are evaluated, insofar they are
>    present; defaults are zero and the sequence's
>    length. The bounds should evaluate to (small)
>    integers. If either bound is negative, the
>    sequence's length is added to it. The resulting
>    bounds are clipped to lie between zero and the
>    sequence's length, inclusive. Finally, the sequence
>    object is asked to replace the slice with the items
>    of the assigned sequence. The length of the slice
>    may be different from the length of the assigned
>    sequence, thus changing the length of the target
>    sequence, if the object allows it.
>    
>V našem příkladu jde o speciální případ, kdy
>mechanismem slice vymezíme všechny prvky seznamu a na
>základě výše popsaného chování se nahradí všemi prvky z
>pravé strany přiřazení. Modifikuje se tedy původní
>seznam. Lépe se to možná dá pochopit na méně speciálním
>případu, kdy slice použijeme jen na část seznamu:
>
>  
>
>>>>a = [1, 2, 3, 4]
>>>>a[1:3]
>>>>        
>>>>
>[2, 3]
>  
>
>>>>a[1:3] = [8, 9, 10]
>>>>a
>>>>        
>>>>
>[1, 8, 9, 10, 4]
>
>Ten popis chování by se dal pro tento konkrétní případ
>přeložit takto:
>
>   Na levé straně přiřazení je zápisem a[1:3] vymezen
>   podseznam s prvky 2 a 3. Tato část je odstraněna a
>   nahrazena prvky seznamu z pravé strany přiřazení. 
>    
>Snad je to teď (i mně ;) trochu jasnější...
>
>pepr
>_______________________________________________
>Python mailing list
>Python na py.cz
>http://www.py.cz/mailman/listinfo/python
>
>  
>




Další informace o konferenci Python