Eu sei Python não tem ponteiros, mas existe uma maneira de ter esse rendimento 2
em vez
>>> 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
sempre tenho o mesmo valor. Não é completamente necessário, mas acho que seria legal.
No PHP, por exemplo, eu posso fazer isso:
<?php
class Form {
public $data = [];
public $fields;
function __construct($fields) {
$this->fields = $fields;
foreach($this->fields as &$field) {
$this->data[$field['id']] = &$field['value'];
}
}
}
$f = new Form([
[
'id' => 'fname',
'value' => 'George'
],
[
'id' => 'lname',
'value' => 'Lucas'
]
]);
echo $f->data['fname'], $f->fields[0]['value']; # George George
$f->data['fname'] = 'Ralph';
echo $f->data['fname'], $f->fields[0]['value']; # Ralph Ralph
Resultado:
GeorgeGeorgeRalphRalph
Ou assim em C ++ (acho que está certo, mas meu C ++ está enferrujado):
#include <iostream>
using namespace std;
int main() {
int* a;
int* b = a;
*a = 1;
cout << *a << endl << *b << endl; # 1 1
return 0;
}
a, b = b, a
.Respostas:
Isso é possível, porque envolve nomes e indexação decorados - ou seja, construções completamente diferentes dos nomes de barras
a
e sobre asb
quais você está perguntando, e com o seu pedido é totalmente impossível. Por que pedir algo impossível e totalmente diferente da (possível) coisa que você realmente quer ?!Talvez você não perceba como nomes de barreiras e nomes decorados são drasticamente diferentes. Quando você se refere a um nome de barra
a
, está obtendo exatamente oa
último objeto vinculado a este escopo (ou uma exceção se não estiver vinculado a esse escopo) - esse é um aspecto tão profundo e fundamental do Python que pode possivelmente seja subvertido. Quando você se refere a um nome decoradox.y
, solicita a um objeto (o objetox
se refere) que forneça "oy
atributo" - e em resposta a essa solicitação, o objeto pode executar cálculos totalmente arbitrários (e a indexação é bastante semelhante: também permite que cálculos arbitrários sejam executados em resposta).Agora, seu exemplo de "desiderata real" é misterioso porque, em cada caso, dois níveis de indexação ou obtenção de atributos estão envolvidos, portanto a sutileza que você deseja pode ser introduzida de várias maneiras. Que outros atributos
form.field
devem ter, por exemplo, além dissovalue
? Sem esses.value
cálculos adicionais , as possibilidades incluiriam:e
A presença de
.value
sugestões para escolher a primeira forma, além de um tipo de invólucro inútil:Se atribuições como
form.field.value = 23
também devem definir a entradaform.data
, o wrapper deve se tornar realmente mais complexo e não tão inútil:O último exemplo é o mais aproximado possível, em Python, do sentido de "um ponteiro" como você deseja - mas é crucial entender que essas sutilezas podem funcionar apenas com indexação e / ou nomes decorados , nunca com nomes de barras como você pediu originalmente!
fonte
Não há como você fazer isso mudando apenas essa linha. Você pode fazer:
Isso cria uma lista, atribui a referência a e, em seguida, b também usa a referência a para definir o primeiro elemento para 2 e acessa usando a variável de referência b.
fonte
a
eb
é a lista, não o valor na lista. As variáveis não estão mudando a atribuição, o objeto é o mesmo objeto. Se ele fosse alterado, como no caso de alterar o número inteiro (cada um dos quais são objetos diferentes),a
agora seria atribuído a outro objeto e não há nada a ser solicitadob
. Aqui,a
não está sendo reatribuído, mas um valor dentro do objeto ao qual está atribuído está sendo alterado. Comob
ainda está vinculado a esse objeto, ele refletirá esse objeto e as alterações nos valores dentro dele.Isto não é um erro, é um recurso :-)
Quando você olha para o operador '=' no Python, não pense em termos de atribuição. Você não atribui coisas, vincula-as. = é um operador de ligação.
Portanto, no seu código, você está dando um nome ao valor 1: a. Então, você está dando o valor em 'a' a nome: b. Então você está vinculando o valor 2 ao nome 'a'. O valor vinculado a b não muda nesta operação.
Vindo de idiomas do tipo C, isso pode ser confuso, mas depois que você se acostuma, descobre que ajuda a ler e raciocinar sobre seu código com mais clareza: o valor que tem o nome 'b' não será alterado, a menos que você alterá-lo explicitamente. E se você 'importar isso', verá que o Zen do Python afirma que o Explícito é melhor do que implícito.
Observe também que linguagens funcionais como Haskell também usam esse paradigma, com grande valor em termos de robustez.
fonte
a = 1; b = a; a = 2;
é exatamente o mesmo em Python, C e Java: b é 1. Por que esse foco em "= não é atribuição, é obrigatório"?a
e,b
enquanto em Python, eles se referem ao mesmo "1" (eu acho). Portanto, se você pudesse alterar o valor de 1 (como nos objetos), seria diferente. O que leva a alguns problemas estranhos de boxe / unboxing, pelo que ouvi.Sim! existe uma maneira de usar uma variável como um ponteiro em python!
Lamento dizer que muitas respostas estavam parcialmente erradas. Em princípio, toda atribuição igual (=) compartilha o endereço de memória (verifique a função id (obj)), mas, na prática, não é assim. Existem variáveis cujo comportamento igual ("=") funciona no último termo como uma cópia do espaço da memória, principalmente em objetos simples (por exemplo, objeto "int") e outras em que não (por exemplo, objetos "list", "dict") .
Aqui está um exemplo de atribuição de ponteiro
Aqui está um exemplo de atribuição de cópia
A atribuição de ponteiro é uma ferramenta bastante útil para criar aliases sem o desperdício de memória extra, em certas situações para a execução de código confortável,
mas é preciso estar ciente desse uso para evitar erros de código.
Para concluir, por padrão, algumas variáveis são nomes de barras (objetos simples como int, float, str, ...) e algumas são ponteiros quando atribuídas entre elas (por exemplo, dict1 = dict2). Como reconhecê-los? tente este experimento com eles. Nos IDEs com painel explorador variável, geralmente parece ser o endereço de memória ("@axbbbbbb ...") na definição de objetos de mecanismo de ponteiro.
Eu sugiro investigar no tópico. Há muitas pessoas que sabem muito mais sobre esse tópico com certeza. (consulte o módulo "ctypes"). Espero que seja útil. Aproveite o bom uso dos objetos! Atenciosamente, José Crespo
fonte
Como você pode ver
a
eb
são apenas dois nomes diferentes que se referem ao mesmo objeto imutável (int)1
. Se você escrever mais tardea = 2
, redesigne o nomea
para um objeto diferente (int)2
, mas ab
referência continua a1
:O que aconteceria se você tivesse um objeto mutável, como uma lista
[1]
?Novamente, estamos nos referindo ao mesmo objeto (lista)
[1]
por dois nomes diferentesa
eb
. No entanto, agora podemos transformar esta lista enquanto ele permanece o mesmo objeto, ea
,b
ambos continuarão fazendo referência a elefonte
De um ponto de vista, tudo é um ponteiro no Python. Seu exemplo funciona muito como o código C ++.
(Um equivalente mais próximo usaria algum tipo de em
shared_ptr<Object>
vez deint*
.)Você pode fazer isso por sobrecarga
__getitem__
naform.data
classe 's.fonte
form.data
não é uma aula. É necessário torná-lo um ou posso substituí-lo em tempo real? (É apenas um ditado em python) Além disso, os dados precisariam ter uma referênciaform
para acessar os campos ... o que torna a implementação desse processo feio.Este é um ponteiro python (diferente de c / c ++)
fonte
Eu escrevi a seguinte classe simples como, efetivamente, uma maneira de emular um ponteiro em python:
Aqui está um exemplo de uso (de uma página de caderno jupyter):
Obviamente, também é fácil fazer isso funcionar para itens de ditado ou atributos de um objeto. Existe até uma maneira de fazer o que o OP pediu, usando globals ():
Isso imprimirá 2, seguidos por 3.
Mexer com o espaço para nome global dessa maneira é uma idéia terrível e transparente, mas mostra que é possível (se desaconselhável) fazer o que o OP solicitou.
O exemplo é, obviamente, bastante inútil. Mas achei essa classe útil no aplicativo para o qual a desenvolvi: um modelo matemático cujo comportamento é governado por vários parâmetros matemáticos configuráveis pelo usuário, de diversos tipos (que, porque dependem de argumentos da linha de comando, não são conhecidos). em tempo de compilação). E uma vez que o acesso a algo tenha sido encapsulado em um objeto Parameter, todos esses objetos podem ser manipulados de maneira uniforme.
Embora não pareça muito com um ponteiro C ou C ++, isso está resolvendo um problema que eu teria resolvido com ponteiros se estivesse escrevendo em C ++.
fonte
O código a seguir emula exatamente o comportamento dos ponteiros em C:
Aqui estão alguns exemplos de uso:
Mas agora é hora de fornecer um código mais profissional, incluindo a opção de excluir ponteiros, que acabei de encontrar na minha biblioteca pessoal:
fonte