Ponteiros em Python?

Eu sei que o Python não tem ponteiros, mas existe uma maneira de ter este rendimento 2 em vez disso

>>> a = 1
>>> b = a # modify this line somehow so that b "points to" a
>>> a = 2
>>> b
1

?


Aqui está um exemplo: eu quero form.data['field'] e form.field.value ter sempre o mesmo valor. Não é completamente necessário, mas acho que seria bom.

Author: Antti Haapala, 2010-06-24

6 answers

Eu quero form.data['field'] e form.field.value Ter sempre o mesmo valor

Isto é viável, porque envolve nomes decorados e indexação -- isto é, completamente construções diferentes dos barenames a e estás a perguntar sobre isso, e porque com o teu pedido é totalmente impossível. Por que pedir algo impossível e totalmente diferente da (possível) coisa que você realmente quer?! Talvez não saibas. perceba como barenames e nomes decorados são drasticamente diferentes. Quando você se refere a um barename a, Você está obtendo exatamente o objeto a que a foi vinculado pela última vez neste escopo (ou uma exceção se ele não estava vinculado neste escopo) -- este é um aspecto tão profundo e fundamental do Python que ele não pode ser subvertido. Quando você se refere a um decorado nome x.y, você está pedindo a um objeto (o objeto x se refere a) para por favor fornecer "o atributo y" -- e em resposta a isso request, the object can perform totally arbitrary computations (and indexing is quite similar: it also allows arbitrary computations to be performed in response).

Agora, o teu exemplo de "desiderata real" é misterioso porque em cada caso dois níveis de indexação ou de atribuição de atributos estão envolvidos, por isso a subtileza que desejas pode ser introduzida de muitas maneiras. Que outros atributos é form.field suponha ter, por exemplo, além de value? Sem mais cálculos .value, as possibilidades incluem:

class Form(object):
   ...
   def __getattr__(self, name):
       return self.data[name]

E

class Form(object):
   ...
   @property
   def data(self):
       return self.__dict__

A presença de .value sugere escolher a primeira forma, mais uma espécie de invólucro inútil:

class KouWrap(object):
   def __init__(self, value):
       self.value = value

class Form(object):
   ...
   def __getattr__(self, name):
       return KouWrap(self.data[name])

Se as atribuições tais form.field.value = 23 também é suposto definir a entrada em form.data, Então o invólucro deve tornar-se mais complexo de facto, e não tudo o que inútil:

class MciWrap(object):
   def __init__(self, data, k):
       self._data = data
       self._k = k
   @property
   def value(self):
       return self._data[self._k]
   @value.setter
   def value(self, v)
       self._data[self._k] = v

class Form(object):
   ...
   def __getattr__(self, name):
       return MciWrap(self.data, name)

O último exemplo é o mais próximo que se chega, em Python, ao sentido de "um ponteiro" como parece querer -- mas é crucial entendo que tais sutilezas nunca pode apenas trabalhar com indexação e/ou nomes decorados, nunca com barenames como você originalmente pediu!

 39
Author: Alex Martelli, 2010-06-24 05:58:29
Não podes fazer isso só mudando essa linha. Você pode fazer:
a = [1]
b = a
a[0] = 2
b[0]

Que cria uma lista, atribui a referência a, então b também, usa a referência a para definir o primeiro elemento para 2, em seguida, acessa usando a variável de referência B.

 38
Author: Matthew Flaschen, 2010-06-24 01:31:14
Não é um bug, é um recurso: -)

Quando você olha para o operador ' = ' em Python, não pense em termos de atribuição. Não se atribui coisas, prende-se. = é um operador de ligação.

Assim, no seu código, você está dando ao valor 1 um nome: a. Então, você está dando o valor em 'a'um nome: B. Então você está ligando o valor 2 ao nome 'a'. O valor ligado a b não muda nesta operação.

Vindo de linguagens semelhantes A C, isto pode ser confuso, mas uma vez você fica acostumado a ele, você descobre que ele ajuda você a ler e raciocinar sobre o seu código mais claramente: o valor que tem o nome " b " não vai mudar a menos que você explicitamente alterá-lo. E se você fizer um 'import this', você verá que o Zen dos Estados Python que é Explícito é melhor do que implícito.

Note bem que linguagens funcionais como Haskell também usam este paradigma, com grande valor em termos de robustez.

 32
Author: David Harks, 2010-06-24 01:55:50
Sim! há uma maneira de usar uma variável como um ponteiro em python! Lamento dizer que muitas das respostas estavam parcialmente erradas. In principle every equal(=) assignation shares the memory address (check the id(obj) function), but in practice it is not such. Existem variáveis cujos igual ("="), o comportamento obras em último termo como uma cópia do espaço de memória, principalmente em objetos simples (por exemplo, "int" objeto), e outros em que não (por exemplo, "lista","dict" objetos). Aqui está um exemplo. of pointer assignation
dict1 = {'first':'hello', 'second':'world'}
dict2 = dict1 # pointer assignation mechanism
dict2['first'] = 'bye'
dict1
>>> {'first':'bye', 'second':'world'}

Aqui está um exemplo de atribuição de cópias

a = 1
b = a # copy of memory mechanism. up to here id(a) == id(b)
b = 2 # new address generation. therefore without pointer behaviour
a
>>> 1

A atribuição de ponteiros é uma ferramenta bastante útil para aliar sem o desperdício de memória extra, em certas situações para executar o código confortável,

class cls_X():
   ...
   def method_1():
      pd1 = self.obj_clsY.dict_vars_for_clsX['meth1'] # pointer dict 1: aliasing
      pd1['var4'] = self.method2(pd1['var1'], pd1['var2'], pd1['var3'])
   #enddef method_1
   ...
#endclass cls_X

Mas é preciso estar ciente desta utilização para evitar erros de código.

Para concluir, por padrão, algumas variáveis são barenames (objetos simples, como int, float, str,...), e alguns são ponteiros quando atribuídos entre eles (por exemplo, dict1 = dict2). Como reconhecê-los? experimenta esta experiência com eles. Em IDEs com o painel Explorer variável normalmente parece ser o endereço de memória ("@axbbbbb...") in the definition of pointer-mechanism objects.

Sugiro que investiguem o assunto. Há muitas pessoas que sabem muito mais sobre este tema com certeza. (ver módulo" ctypes"). Espero que seja útil. Aproveite o bom uso dos objetos! Regards, José Crespo
 16
Author: José Crespo Barrios, 2014-09-18 09:56:17

De um ponto de vista, Tudo é um ponteiro em Python. O seu exemplo funciona muito como o código C++.

int* a = new int(1);
int* b = a;
a = new int(2);
cout << *b << endl;   // prints 1

(um equivalente mais próximo usaria algum tipo de shared_ptr<Object> em vez de int*.)

Eis um exemplo: formulario.dados ["Campo"] e formulario.campo.valor para ter sempre o o mesmo valor. Não é completamente necessário, mas acho que seria bom.

Pode fazer isto sobrecarregando __getitem__ na classe de form.data.

 11
Author: dan04, 2010-06-24 03:09:57
id(1)
1923344848  # identity of the location in my memory    
>> a = 1
>> b = a  # or equivalently b = 1, because 1 is immutable
>> id(a)
1923344848
>> id(b)
1923344848

Como podem ver a e b são apenas Nomes que se referem ao mesmo objecto 1. Se mais tarde escrever a = 2, irá atribuir o nome a a um objecto diferente 2, mas não ao b que irá continuar a referir-se a 1:

>> id(2)
1923344880
>> a = 2
>> id(a)
1923344880  # same as id(2)
>> id(b)
1923344848  # same as id(1)
O que acontecerá se tiver um objecto mutável?
>> id([1])
328817608
>> id([1])
328664968  # different
>> a = [1]
>> id(a)
328817800
>> id(a)
328817800  # same as before
>> b = a  # not equivalent to b = [1]
>> id(b)
328817800  # same as id(a)

Agora, estás a referir-te ao mesmo objecto de Lista pelos nomes a e b. Você pode mutar esta lista, mas ela permanecerá o mesmo objeto, e a e b ambos vão continuar a referir-se a ele

>> a[0] = 2
>> a
[2]
>> b
[2]
>> id(a)
328817800  # same as before
>> id(b)
328817800  # same as before
 3
Author: Andyk, 2018-02-14 11:10:54