Con trỏ trong Python?


124

Tôi biết Python không có con trỏ, nhưng có cách nào để có lợi nhuận này 2thay thế

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

?


Đây là một ví dụ: Tôi muốn form.data['field']form.field.valueluôn có cùng một giá trị. Nó không hoàn toàn cần thiết, nhưng tôi nghĩ nó sẽ tốt.


Trong PHP, ví dụ, tôi có thể làm điều này:

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

Đầu ra:

GeorgeGeorgeRalphRalph

tưởng tượng


Hoặc như thế này trong C ++ (tôi nghĩ điều này đúng, nhưng C ++ của tôi bị gỉ):

#include <iostream>
using namespace std;

int main() {
    int* a;
    int* b = a;
    *a = 1;
    cout << *a << endl << *b << endl; # 1 1

    return 0;
}

28
Có lẽ tôi có thể hỏi một câu hỏi tương tự như của S.Lott (nhưng hiệu quả hơn): bạn có thể cho chúng tôi xem một số mã thực mà bạn muốn thực hiện điều này không? Có lẽ ngay cả trong một ngôn ngữ khác phù hợp với sở thích của bạn? Có khả năng vấn đề bạn đang cố gắng giải quyết sẽ dẫn đến một giải pháp Pythonic hơn và việc tập trung vào "Tôi muốn con trỏ" đang che khuất câu trả lời thực sự.
Ned Batchelder

8
Nó không cần nhiều trí tưởng tượng; Tôi có thể nghĩ ra hàng tá lý do để muốn làm điều này. Nó không chỉ là cách nó được thực hiện trong các ngôn ngữ ít con trỏ như Python; bạn cần phải bọc nó trong một hộp chứa không bất biến, như trong câu trả lời của Matt.
Glenn Maynard

14
Bạn sẽ không viết hàm hoán đổi bằng Python. Bạn sẽ viết a, b = b, a.
dan04

3
-1: Cấu trúc trong câu hỏi là (a) vô nghĩa, và (b) dường như không ai có thể đưa ra một ví dụ làm cho nó hợp lý. Nói có "hàng tá lý do" không giống như đăng một ví dụ.
S.Lott

1
@Mark: Ngoài ra, tôi không "không đồng ý". Tôi bối rối. Tôi đang đặt một câu hỏi, đang tìm cách để hiểu đây là gì và tại sao bạn cho rằng nó quan trọng đến vậy.
S.Lott

Câu trả lời:


48

Tôi muốn form.data['field']form.field.valueluôn có cùng một giá trị

Đây là khả thi, bởi vì nó liên quan đến tên trang trí và lập chỉ mục - ví dụ, hoàn toàn cấu trúc khác nhau từ barenames abrằng bạn đang yêu cầu về, và cho yêu cầu của bạn là hoàn toàn không thể. Tại sao lại yêu cầu một điều không thể hoàn toàn khác với điều (có thể) mà bạn thực sự muốn ?!

Có thể bạn không nhận ra tên trần và tên được trang trí khác nhau đáng kể như thế nào. Khi bạn tham chiếu đến tên trần a, bạn đang nhận được chính xác đối tượng ađược liên kết cuối cùng trong phạm vi này (hoặc một ngoại lệ nếu nó không bị ràng buộc trong phạm vi này) - đây là một khía cạnh sâu sắc và cơ bản của Python mà nó có thể không thể bị lật đổ. Khi bạn tham chiếu đến một tên được trang tríx.y , bạn đang yêu cầu một đối tượng (đối tượng được xtham chiếu đến) vui lòng cung cấp " ythuộc tính" - và để đáp ứng yêu cầu đó, đối tượng có thể thực hiện các phép tính hoàn toàn tùy ý (và việc lập chỉ mục khá giống nhau: nó cũng cho phép thực hiện các phép tính tùy ý).

Bây giờ, ví dụ "desiderata thực tế" của bạn là bí ẩn vì trong mỗi trường hợp, hai cấp độ lập chỉ mục hoặc nhận thuộc tính đều có liên quan, vì vậy sự tinh tế mà bạn khao khát có thể được giới thiệu theo nhiều cách. form.fieldVí dụ, ngoài ra còn có những thuộc tính nào khác value? Nếu không có sự .valuetính toán thêm , các khả năng sẽ bao gồm:

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

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

Sự hiện diện của .valuegợi ý chọn biểu mẫu đầu tiên, cộng với một loại trình bao bọc vô dụng:

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

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

Nếu các phép gán như vậy form.field.value = 23cũng được cho là để đặt mục nhập vào form.data, thì trình bao bọc thực sự phải trở nên phức tạp hơn, và không phải tất cả những điều đó đều vô dụng:

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)

Ví dụ thứ hai gần giống với nghĩa "một con trỏ" như bạn muốn - nhưng điều quan trọng là phải hiểu rằng sự tinh tế như vậy chỉ có thể hoạt động với lập chỉ mục và / hoặc tên được trang trí , không bao giờ với tên trần như bạn đã hỏi ban đầu!


23
Tôi hỏi nó theo cách tôi đã làm bởi vì tôi hy vọng có được một giải pháp chung có thể hoạt động cho mọi thứ ngay từ "tên trần" và tôi không có một trường hợp cụ thể nào vào thời điểm đó - chỉ là tôi đã gặp phải vấn đề này vấn đề với lần lặp trước của dự án này và tôi không muốn gặp lại lần nữa. Dù sao, đây là một câu trả lời tuyệt vời! Tuy nhiên, sự hoài nghi ít được đánh giá cao hơn.
mở cửa

2
@Mark, hãy xem các bình luận trên Q của bạn và bạn sẽ thấy rằng "sự hoài nghi" là một phản ứng rộng rãi - và A được bình chọn nhiều nhất đang nói với bạn "đừng làm điều đó, hãy vượt qua nó", tiếp theo là đi "nó chỉ là như thế nào". Mặc dù bạn có thể không "đánh giá cao" những người hiểu biết về Python phản ứng với sự ngạc nhiên với các thông số kỹ thuật ban đầu của bạn, nhưng bản thân họ lại khá ngạc nhiên ;-).
Alex Martelli

30
Có, nhưng bạn dường như ngạc nhiên tại tôi thiếu kiến thức Python ... như thể chúng tôi là một loài ngoại: P
mpen

51

Không có cách nào bạn có thể làm điều đó chỉ thay đổi dòng đó. Bạn có thể làm:

a = [1]
b = a
a[0] = 2
b[0]

Điều đó tạo ra một danh sách, gán tham chiếu cho a, sau đó b cũng sử dụng tham chiếu để đặt phần tử đầu tiên thành 2, sau đó truy cập bằng cách sử dụng biến tham chiếu b.


17
Đó chính xác là loại không nhất quán mà tôi ghét về Python và các ngôn ngữ động này. (Vâng vâng, nó không thực sự "không nhất quán" vì bạn đang thay đổi một thuộc tính chứ không phải là tham chiếu nhưng tôi vẫn không thích nó)
mpen

10
@Mark: đúng vậy. Tôi biết vô số (tốt, một vài) người đã dành hàng giờ đồng hồ để tìm kiếm "lỗi" trong mã của họ và sau đó phát hiện ra rằng đó là do danh sách không được sao chép cứng.
houbysoft

14
Không có sự mâu thuẫn. Và nó không liên quan gì đến cuộc tranh luận static v. Dynamic. Nếu chúng là hai tham chiếu đến cùng một Java ArrayList, nó sẽ giống nhau, cú pháp modulo. Nếu bạn sử dụng các đối tượng không thay đổi (như bộ giá trị), bạn không phải lo lắng về việc đối tượng bị thay đổi thông qua một tham chiếu khác.
Matthew Flaschen

Tôi đã sử dụng điều này vài lần, phổ biến nhất là để giải quyết vấn đề thiếu "nonlocal" của 2.x. Nó không phải là điều đẹp nhất để làm, nhưng nó hoạt động tốt trong một thời gian ngắn.
Glenn Maynard

1
Điều này hoàn toàn không nhất quán vì đối tượng bạn đang gán ablà danh sách, không phải giá trị trong danh sách. Các biến không thay đổi phép gán, đối tượng là cùng một đối tượng. Nếu nó thay đổi, như trong trường hợp thay đổi số nguyên (mỗi trong số đó là các đối tượng khác nhau), abây giờ sẽ được gán cho một đối tượng khác và không có gì nhắc nhở bđể làm theo. Ở đây, anó không được gán lại, đúng hơn là một giá trị bên trong đối tượng mà nó được gán đang thay đổi. Vì bvẫn còn bị ràng buộc với đối tượng đó, nó sẽ phản ánh đối tượng đó và những thay đổi đối với các giá trị bên trong nó.
arkigos

34

Nó không phải là một lỗi, đó là một tính năng :-)

Khi bạn nhìn vào toán tử '=' trong Python, đừng nghĩ về mặt gán. Bạn không chỉ định mọi thứ, bạn ràng buộc chúng. = là một toán tử ràng buộc.

Vì vậy, trong mã của bạn, bạn đang đặt tên cho giá trị 1: a. Sau đó, bạn đang cho giá trị trong 'a' một tên: b. Sau đó, bạn đang ràng buộc giá trị 2 với tên 'a'. Giá trị liên kết với b không thay đổi trong hoạt động này.

Đến từ các ngôn ngữ giống C, điều này có thể gây nhầm lẫn, nhưng khi bạn đã quen với nó, bạn sẽ thấy rằng nó giúp bạn đọc và suy luận về mã của mình rõ ràng hơn: giá trị có tên 'b' sẽ không thay đổi trừ khi bạn thay đổi nó một cách rõ ràng. Và nếu bạn thực hiện 'import this', bạn sẽ thấy rằng Zen của Python nói rằng Explicit tốt hơn là ẩn.

Cũng cần lưu ý rằng các ngôn ngữ chức năng như Haskell cũng sử dụng mô hình này, có giá trị lớn về độ mạnh mẽ.


39
Bạn biết đấy, tôi đã đọc những câu trả lời như thế này hàng chục lần và tôi chưa bao giờ hiểu nó. Hành vi của a = 1; b = a; a = 2;hoàn toàn giống nhau trong Python, C và Java: b là 1. Tại sao điều này lại tập trung vào "= không phải là gán, nó là ràng buộc"?
Ned Batchelder

4
Bạn chỉ định mọi thứ. Đó là lý do tại sao nó được gọi là câu lệnh gán . Sự khác biệt mà bạn đang nói không có ý nghĩa. Và điều này không liên quan gì đến biên dịch v. Thông dịch hoặc tĩnh v. Động. Java là một ngôn ngữ đã biên dịch với tính năng kiểm tra kiểu tĩnh và nó cũng không có con trỏ.
Matthew Flaschen

3
Còn C ++ thì sao? "b" có thể là một tham chiếu đến "a". Hiểu được sự khác biệt giữa gán và ràng buộc là rất quan trọng để hiểu đầy đủ lý do tại sao Mark không thể làm những gì anh ấy muốn làm và cách các ngôn ngữ như Python được thiết kế. Về mặt khái niệm (không nhất thiết phải triển khai), "a = 1" không ghi đè khối bộ nhớ có tên "a" bằng 1; nó chỉ định tên "a" cho đối tượng đã tồn tại "1", về cơ bản khác với những gì xảy ra trong C. Đó là lý do tại sao con trỏ như một khái niệm không thể tồn tại trong Python - chúng sẽ trở nên cũ trong lần tiếp theo biến ban đầu đã được "gán trên".
Glenn Maynard

1
@dw: Tôi thích cách nghĩ này về nó! "Ràng buộc" là một từ tốt. @Ned: Đầu ra giống nhau, vâng, nhưng trong C giá trị của "1" được sao chép sang cả hai abtrong khi trong Python, cả hai đều tham chiếu đến cùng "1" (tôi nghĩ). Vì vậy, nếu bạn có thể thay đổi giá trị của 1 (như với các đối tượng), nó sẽ khác. Tôi nghe thấy điều này dẫn đến một số vấn đề quyền anh / mở hộp kỳ lạ.
mpen

4
Sự khác biệt giữa Python và C không phải là "gán" nghĩa là gì. Đó là những gì "biến" có nghĩa là.
dan04

28

Đúng! có một cách để sử dụng một biến làm con trỏ trong python!

Tôi rất tiếc phải nói rằng nhiều câu trả lời sai một phần. Về nguyên tắc, mọi phép gán bằng (=) đều chia sẻ địa chỉ bộ nhớ (kiểm tra hàm id (obj)), nhưng trên thực tế thì không phải như vậy. Có những biến có hành vi bằng ("=") hoạt động trong thuật ngữ cuối cùng như một bản sao của không gian bộ nhớ, chủ yếu là trong các đối tượng đơn giản (ví dụ: đối tượng "int") và các biến khác thì không (ví dụ: đối tượng "list", "dict") .

Đây là một ví dụ về chỉ định con trỏ

dict1 = {'first':'hello', 'second':'world'}
dict2 = dict1 # pointer assignation mechanism
dict2['first'] = 'bye'
dict1
>>> {'first':'bye', 'second':'world'}

Đây là một ví dụ về chuyển nhượng bản sao

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

Chỉ định con trỏ là một công cụ khá hữu ích để tạo răng cưa mà không tốn thêm bộ nhớ, trong một số tình huống nhất định để thực hiện mã thoải mái,

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

nhưng người ta phải nhận thức được việc sử dụng này để ngăn chặn các lỗi mã.

Để kết luận, theo mặc định, một số biến là tên trần (các đối tượng đơn giản như int, float, str, ...) và một số là con trỏ khi được gán giữa chúng (ví dụ: dict1 = dict2). Làm thế nào để nhận ra chúng? chỉ cần thử thử nghiệm này với họ. Trong các IDE có bảng điều khiển khám phá biến thường xuất hiện là địa chỉ bộ nhớ ("@axbbbbbb ...") trong định nghĩa của các đối tượng cơ chế con trỏ.

Tôi đề nghị điều tra trong chủ đề. Có rất nhiều người biết nhiều hơn về chủ đề này chắc chắn. (xem mô-đun "ctypes"). Tôi hi vọng nó hữu ích. Tận hưởng việc sử dụng tốt các đồ vật! Trân trọng, José Crespo


Vì vậy, tôi phải sử dụng từ điển để truyền một biến bằng cách tham chiếu đến một hàm và tôi không thể chuyển một biến bằng tham chiếu bằng cách sử dụng int hoặc một chuỗi?
Sam

13
>> id(1)
1923344848  # identity of the location in memory where 1 is stored
>> id(1)
1923344848  # always the same
>> a = 1
>> b = a  # or equivalently b = 1, because 1 is immutable
>> id(a)
1923344848
>> id(b)  # equal to id(a)
1923344848

Như bạn có thể thấy abchỉ là hai tên khác nhau tham chiếu đến cùng một đối tượng bất biến (int) 1. Nếu sau này bạn viết a = 2, bạn gán lại tên acho một đối tượng khác (int) 2, nhưng bvẫn tiếp tục tham chiếu đến 1:

>> id(2)
1923344880
>> a = 2
>> id(a)
1923344880  # equal to id(2)
>> b
1           # b hasn't changed
>> id(b)
1923344848  # equal to id(1)

Điều gì sẽ xảy ra nếu bạn có một đối tượng có thể thay đổi thay thế, chẳng hạn như một danh sách [1]?

>> id([1])
328817608
>> id([1])
328664968  # different from the previous id, because each time a new list is created
>> a = [1]
>> id(a)
328817800
>> id(a)
328817800 # now same as before
>> b = a
>> id(b)
328817800  # same as id(a)

Một lần nữa, chúng tôi đang tham chiếu đến cùng một đối tượng (danh sách) [1]bằng hai tên khác nhau ab. Tuy nhiên bây giờ chúng ta có thể đột biến danh sách này trong khi nó vẫn là cùng một đối tượng, và a, bcả hai sẽ tiếp tục tham khảo với nó

>> a[0] = 2
>> a
[2]
>> b
[2]
>> id(a)
328817800  # same as before
>> id(b)
328817800  # same as before

1
Cảm ơn bạn đã giới thiệu hàm id. Điều này giải quyết nhiều nghi ngờ của tôi.
haudoing

12

Theo một quan điểm, mọi thứ đều là một con trỏ trong Python. Ví dụ của bạn hoạt động rất giống với mã C ++.

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

(Tương đương gần hơn sẽ sử dụng một số loại shared_ptr<Object>thay vì int*.)

Đây là một ví dụ: Tôi muốn form.data ['field'] và form.field.value luôn có cùng giá trị. Nó không hoàn toàn cần thiết, nhưng tôi nghĩ nó sẽ tốt.

Bạn có thể làm điều này bằng cách nạp chồng __getitem__vào form.datalớp của.


form.datakhông phải là một lớp học. Có cần thiết phải tạo nó một cái hay tôi có thể ghi đè nó ngay lập tức? (Nó chỉ là một lệnh python) Ngoài ra, dữ liệu sẽ phải có một tham chiếu trở lại formđể truy cập các trường ... điều này làm cho việc triển khai điều này trở nên xấu xí.
mpen

1

Đây là một con trỏ python (khác với c / c ++)

>>> a = lambda : print('Hello')
>>> a
<function <lambda> at 0x0000018D192B9DC0>
>>> id(a) == int(0x0000018D192B9DC0)
True
>>> from ctypes import cast, py_object
>>> cast(id(a), py_object).value == cast(int(0x0000018D192B9DC0), py_object).value
True
>>> cast(id(a), py_object).value
<function <lambda> at 0x0000018D192B9DC0>
>>> cast(id(a), py_object).value()
Hello

0

Tôi đã viết một lớp đơn giản sau đây như một cách hiệu quả để mô phỏng một con trỏ trong python:

class Parameter:
    """Syntactic sugar for getter/setter pair
    Usage:

    p = Parameter(getter, setter)

    Set parameter value:
    p(value)
    p.val = value
    p.set(value)

    Retrieve parameter value:
    p()
    p.val
    p.get()
    """
    def __init__(self, getter, setter):
        """Create parameter

        Required positional parameters:
        getter: called with no arguments, retrieves the parameter value.
        setter: called with value, sets the parameter.
        """
        self._get = getter
        self._set = setter

    def __call__(self, val=None):
        if val is not None:
            self._set(val)
        return self._get()

    def get(self):
        return self._get()

    def set(self, val):
        self._set(val)

    @property
    def val(self):
        return self._get()

    @val.setter
    def val(self, val):
        self._set(val)

Đây là một ví dụ về cách sử dụng (từ trang sổ ghi chép jupyter):

l1 = list(range(10))
def l1_5_getter(lst=l1, number=5):
    return lst[number]

def l1_5_setter(val, lst=l1, number=5):
    lst[number] = val

[
    l1_5_getter(),
    l1_5_setter(12),
    l1,
    l1_5_getter()
]

Out = [5, None, [0, 1, 2, 3, 4, 12, 6, 7, 8, 9], 12]

p = Parameter(l1_5_getter, l1_5_setter)

print([
    p(),
    p.get(),
    p.val,
    p(13),
    p(),
    p.set(14),
    p.get()
])
p.val = 15
print(p.val, l1)

[12, 12, 12, 13, 13, None, 14]
15 [0, 1, 2, 3, 4, 15, 6, 7, 8, 9]

Tất nhiên, cũng dễ dàng thực hiện điều này đối với các mục hoặc thuộc tính dict của một đối tượng. Thậm chí còn có một cách để thực hiện những gì OP yêu cầu, bằng cách sử dụng các hình cầu ():

def setter(val, dict=globals(), key='a'):
    dict[key] = val

def getter(dict=globals(), key='a'):
    return dict[key]

pa = Parameter(getter, setter)
pa(2)
print(a)
pa(3)
print(a)

Điều này sẽ in ra 2, tiếp theo là 3.

Lộn xộn với không gian tên toàn cầu theo cách này rõ ràng là một ý tưởng khủng khiếp, nhưng nó cho thấy rằng có thể (nếu không thể thực hiện được) để thực hiện những gì OP yêu cầu.

Tất nhiên, ví dụ này khá vô nghĩa. Nhưng tôi nhận thấy lớp này hữu ích trong ứng dụng mà tôi đã phát triển nó: một mô hình toán học có hành vi được điều chỉnh bởi nhiều tham số toán học do người dùng thiết lập, thuộc nhiều loại khác nhau (mà vì chúng phụ thuộc vào các đối số dòng lệnh, không được biết đến tại thời điểm biên dịch). Và một khi quyền truy cập vào một thứ gì đó đã được gói gọn trong một đối tượng Tham số, tất cả các đối tượng đó có thể được thao tác theo một cách thống nhất.

Mặc dù nó trông không giống một con trỏ C hoặc C ++, nhưng điều này đang giải quyết một vấn đề mà tôi sẽ giải quyết với con trỏ nếu tôi viết bằng C ++.


0

Đoạn mã sau mô phỏng chính xác hành vi của con trỏ trong C:

from collections import deque # more efficient than list for appending things
pointer_storage = deque()
pointer_address = 0

class new:    
    def __init__(self):
        global pointer_storage    
        global pointer_address

        self.address = pointer_address
        self.val = None        
        pointer_storage.append(self)
        pointer_address += 1


def get_pointer(address):
    return pointer_storage[address]

def get_address(p):
    return p.address

null = new() # create a null pointer, whose address is 0    

Dưới đây là các ví dụ sử dụng:

p = new()
p.val = 'hello'
q = new()
q.val = p
r = new()
r.val = 33

p = get_pointer(3)
print(p.val, flush = True)
p.val = 43
print(get_pointer(3).val, flush = True)

Nhưng bây giờ đã đến lúc đưa ra một đoạn mã chuyên nghiệp hơn, bao gồm tùy chọn xóa con trỏ, mà tôi vừa tìm thấy trong thư viện cá nhân của mình:

# C pointer emulation:

from collections import deque # more efficient than list for appending things
from sortedcontainers import SortedList #perform add and discard in log(n) times


class new:      
    # C pointer emulation:
    # use as : p = new()
    #          p.val             
    #          p.val = something
    #          p.address
    #          get_address(p) 
    #          del_pointer(p) 
    #          null (a null pointer)

    __pointer_storage__ = SortedList(key = lambda p: p.address)
    __to_delete_pointers__ = deque()
    __pointer_address__ = 0 

    def __init__(self):      

        self.val = None 

        if new.__to_delete_pointers__:
            p = new.__to_delete_pointers__.pop()
            self.address = p.address
            new.__pointer_storage__.discard(p) # performed in log(n) time thanks to sortedcontainers
            new.__pointer_storage__.add(self)  # idem

        else:
            self.address = new.__pointer_address__
            new.__pointer_storage__.add(self)
            new.__pointer_address__ += 1


def get_pointer(address):
    return new.__pointer_storage__[address]


def get_address(p):
    return p.address


def del_pointer(p):
    new.__to_delete_pointers__.append(p)

null = new() # create a null pointer, whose address is 0

Tôi nghĩ bạn vừa đóng hộp các giá trị theo một cách kỳ lạ.
mở cửa vào

Ý bạn là: một "cách thông minh" hay một "cách không thông minh"?
MikeTeX

Uhhh ... Tôi đang đấu tranh để xem một ca sử dụng hợp lệ cho bộ nhớ toàn cầu được lập chỉ mục bởi một số ngẫu nhiên.
mpen

Ví dụ sử dụng: Tôi là một kỹ sư thuật toán và tôi phải làm việc với các lập trình viên. Tôi làm việc với Python và chúng làm việc với C ++. Đôi khi, họ yêu cầu tôi viết một thuật toán cho họ, và tôi viết nó càng gần với C ++ càng tốt để thuận tiện cho họ. Con trỏ là ví dụ hữu ích cho cây nhị phân, vv
MikeTeX

Lưu ý: nếu lưu trữ toàn cục làm phiền, bạn có thể bao gồm nó như một biến toàn cục ở cấp độ của chính lớp đó, điều này có lẽ sẽ thanh lịch hơn.
MikeTeX
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.