Hướng dẫn python access class attribute without instance - Thuộc tính lớp truy cập python không có phiên bản

Tôi đã tự hỏi nếu có thể sử dụng một thuộc tính của một lớp từ một tệp khác mà không tạo một đối tượng từ lớp đó, ví dụ, nếu tôi có class_a trong file_a và tôi nhập class_a vào file_b, tôi có phải sử dụng class_a làm đối tượng trong FILE_B để truy cập các thuộc tính của nó?

hỏi ngày 9 tháng 7 năm 2017 lúc 20:52Jul 9, 2017 at 20:52

Hướng dẫn python access class attribute without instance - Thuộc tính lớp truy cập python không có phiên bản

2

Cách đơn giản nhất:

In [12]: class MyClass(object):
...:         attr = 'attr value'

In [15]: MyClass.attr
Out[15]: 'attr value'

Bạn cũng có thể sử dụng thuộc tính __dict__:

__dict__ là từ điển chứa không gian tên của lớp.

In [15]: MyClass.__dict__.get('attr', None)
Out[15]: 'attr value'

Sử dụng Bộ trang trí StaticMethod nếu bạn cần sử dụng phương pháp:

In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2

Đã trả lời ngày 9 tháng 7 năm 2017 lúc 21:00Jul 9, 2017 at 21:00

SaypysaypySayPy

5364 Huy hiệu bạc13 Huy hiệu Đồng4 silver badges13 bronze badges

6

Thực sự không có lý do để tạo một đối tượng mới trong khác để sử dụng các thuộc tính và phương thức của một đối tượng khác.

Bạn chỉ muốn tạo một phiên bản của class_a trong file_b để sử dụng các thuộc tính và phương thức của nó.

Ví dụ:

import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()

Đọc thêm về OOP tại đây http://www.python-course.eu/object_oriented_programming.php

Đã trả lời ngày 9 tháng 7 năm 2017 lúc 21:05Jul 9, 2017 at 21:05

Hướng dẫn python access class attribute without instance - Thuộc tính lớp truy cập python không có phiên bản

Fortuneefressioneefortunee

3,4262 huy hiệu vàng16 Huy hiệu bạc24 Huy hiệu đồng2 gold badges16 silver badges24 bronze badges

2

Tôi đã có một cuộc phỏng vấn lập trình gần đây, một màn hình điện thoại trong đó chúng tôi đã sử dụng một trình soạn thảo văn bản hợp tác.

Tôi đã được yêu cầu thực hiện một API nhất định và chọn làm như vậy trong Python. Tóm tắt về tuyên bố vấn đề, hãy nói rằng tôi cần một lớp có các trường hợp lưu trữ một số

In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
7 và một số
In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
8.

Tôi hít một hơi thật sâu và bắt đầu gõ. Sau một vài dòng, tôi đã có một cái gì đó như thế này:

class Service(object):
    data = []

    def __init__(self, other_data):
        self.other_data = other_data
    ...

Người phỏng vấn của tôi đã ngăn tôi lại:

  • Người phỏng vấn: Dòng đó:
    In [12]: class MyClass(object):
    ...:         @staticmethod
    ...:         def the_static_method(x):
    ...:             print(x)
    
    
    In [15]: MyClass.the_static_method(2)
    Out[15]: 2
    
    9. Tôi không nghĩ rằng, Python hợp lệ?
  • Tôi: Tôi đã rất chắc chắn. Nó chỉ đặt một giá trị mặc định cho thuộc tính thể hiện.
  • Người phỏng vấn: Khi nào mã đó được thực thi?
  • Tôi: Tôi không thực sự chắc chắn. Tôi chỉ cần sửa nó để tránh nhầm lẫn.

Để tham khảo và để cung cấp cho bạn một ý tưởng về những gì tôi sẽ làm, ở đây, cách tôi sửa đổi mã:

class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...

Hóa ra, cả hai chúng tôi đều sai. Câu trả lời thực sự nằm trong việc hiểu sự khác biệt giữa các thuộc tính lớp Python và các thuộc tính thể hiện Python.

Hướng dẫn python access class attribute without instance - Thuộc tính lớp truy cập python không có phiên bản

Lưu ý: Nếu bạn có một chuyên gia xử lý các thuộc tính của lớp, bạn có thể bỏ qua trước để sử dụng các trường hợp.

Thuộc tính lớp Python

Người phỏng vấn của tôi đã sai ở chỗ mã trên có hiệu lực về mặt cú pháp.

Tôi cũng đã sai ở chỗ nó không phải là một giá trị mặc định của người dùng cho thuộc tính thể hiện. Thay vào đó, nó xác định

In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
7 là thuộc tính lớp có giá trị
import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()
1.

Theo kinh nghiệm của tôi, các thuộc tính lớp Python là một chủ đề mà nhiều người biết điều gì đó, nhưng ít ai hiểu hoàn toàn.

Biến lớp Python so với biến thể hiện: Điều gì khác biệt?

Một thuộc tính lớp Python là một thuộc tính của lớp (tròn, tôi biết), thay vì một thuộc tính của một thể hiện của một lớp.

Hãy để sử dụng một ví dụ về lớp Python để minh họa sự khác biệt. Ở đây,

import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()
2 là thuộc tính lớp và
import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()
3 là một thuộc tính thể hiện:

class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

Lưu ý rằng tất cả các trường hợp của lớp đều có quyền truy cập vào

import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()
2 và nó cũng có thể được truy cập dưới dạng thuộc tính của chính lớp:

foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1

Đối với các lập trình viên Java hoặc C ++, thuộc tính lớp tương tự nhưng không giống hệt với thành viên tĩnh. Chúng tôi sẽ thấy họ khác nhau như thế nào sau này.

Không gian tên lớp so với trường hợp

Để hiểu những gì xảy ra ở đây, hãy để nói chuyện ngắn gọn về các không gian tên Python.Python namespaces.

Một không gian tên là một ánh xạ từ tên đến các đối tượng, với thuộc tính không có mối quan hệ nào giữa các tên trong các không gian tên khác nhau. Họ thường được thực hiện dưới dạng từ điển Python, mặc dù điều này được trừu tượng hóa.

Tùy thuộc vào ngữ cảnh, bạn có thể cần truy cập không gian tên bằng cú pháp DOT (ví dụ:

import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()
5) hoặc làm biến cục bộ (ví dụ:
import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()
6). Như một ví dụ cụ thể:

class MyClass(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
MyClass.class_var
## 1

Các lớp Python và các trường hợp của các lớp mỗi lớp có các không gian tên riêng biệt được đại diện bởi các thuộc tính được xác định trước

import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()
7 và
import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()
8, tương ứng.

Khi bạn cố gắng truy cập một thuộc tính từ một thể hiện của một lớp, trước tiên nó xem xét không gian tên thể hiện của nó. Nếu nó tìm thấy thuộc tính, nó sẽ trả về giá trị liên quan. Nếu không, sau đó nó nhìn vào không gian tên lớp và trả về thuộc tính (nếu nó có mặt, ném một lỗi khác). Ví dụ:

foo = MyClass(2)

## Finds i_var in foo's instance namespace
foo.i_var
## 2

## Doesn't find class_var in instance namespace…
## So look's in class namespace (MyClass.__dict__)
foo.class_var
## 1

Không gian tên trường hợp có quyền tối cao đối với không gian tên lớp: Nếu có một thuộc tính có cùng tên trong cả hai, không gian tên trường hợp sẽ được kiểm tra trước và giá trị của nó được trả về. Tại đây, một phiên bản đơn giản hóa của mã (nguồn) để tra cứu thuộc tính:

In [15]: MyClass.__dict__.get('attr', None)
Out[15]: 'attr value'
0

Và, ở dạng trực quan:

Hướng dẫn python access class attribute without instance - Thuộc tính lớp truy cập python không có phiên bản

Cách phân công thuộc tính lớp

Với suy nghĩ này, chúng ta có thể hiểu được cách thức các thuộc tính lớp Python xử lý việc gán:

  • Nếu một thuộc tính lớp được đặt bằng cách truy cập lớp, nó sẽ ghi đè giá trị cho tất cả các trường hợp. Ví dụ:

    In [15]: MyClass.__dict__.get('attr', None)
    Out[15]: 'attr value'
    
    1

    Ở cấp độ không gian tên, chúng tôi đã thiết lập

    import Class_A
    
    #instance of Class_A
    classA = Class_A('params')
    
    #property1 is a property in classA
    classA.property1
    
    #doSomething is a method in classA
    classA.doSomething()
    
    9. . Sau đó, khi chúng tôi truy cập
    class Service(object):
        data = []
    
        def __init__(self, other_data):
            self.other_data = other_data
        ...
    
    2,
    import Class_A
    
    #instance of Class_A
    classA = Class_A('params')
    
    #property1 is a property in classA
    classA.property1
    
    #doSomething is a method in classA
    classA.doSomething()
    
    2 có giá trị mới trong không gian tên lớp và do đó 2 được trả về.

  • Nếu một biến lớp Paython được đặt bằng cách truy cập một thể hiện, nó sẽ chỉ ghi đè giá trị cho trường hợp đó. Điều này về cơ bản ghi đè biến lớp và biến nó thành một biến thể hiện có sẵn, bằng trực giác, chỉ cho trường hợp đó. Ví dụ:

    In [15]: MyClass.__dict__.get('attr', None)
    Out[15]: 'attr value'
    
    2

    Ở cấp độ không gian tên. Trả lại 1.

Tính đột biến

Câu hỏi câu hỏi: Điều gì sẽ xảy ra nếu thuộc tính lớp của bạn có một loại có thể thay đổi? Bạn có thể thao tác (cắt xén?) Thuộc tính lớp bằng cách truy cập nó thông qua một trường hợp cụ thể và đến lượt nó, kết thúc thao tác đối tượng được tham chiếu mà tất cả các trường hợp đang truy cập (như được chỉ ra bởi Timothy Wiseman).mutable type? You can manipulate (mutilate?) the class attribute by accessing it through a particular instance and, in turn, end up manipulating the referenced object that all instances are accessing (as pointed out by Timothy Wiseman).

Điều này được thể hiện tốt nhất bằng ví dụ. Hãy để Lừa quay trở lại

class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
1 mà tôi đã xác định trước đó và xem cách sử dụng biến lớp của tôi có thể dẫn đến các vấn đề xuống đường.

class Service(object):
    data = []

    def __init__(self, other_data):
        self.other_data = other_data
    ...

Mục tiêu của tôi là có danh sách trống (

import Class_A

#instance of Class_A
classA = Class_A('params')

#property1 is a property in classA
classA.property1

#doSomething is a method in classA
classA.doSomething()
1) là giá trị mặc định cho
In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
7 và cho mỗi trường hợp
class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
1 để có dữ liệu riêng sẽ bị thay đổi theo thời gian trên cơ sở theo trường hợp. Nhưng trong trường hợp này, chúng tôi có được hành vi sau (nhớ lại rằng
class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
1 có một số đối số
In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
8, đó là tùy ý trong ví dụ này):

In [15]: MyClass.__dict__.get('attr', None)
Out[15]: 'attr value'
4

Đây không phải là điều tốt, thay đổi biến lớp thông qua một trường hợp thay đổi nó cho tất cả các trường hợp khác!

Ở cấp độ không gian tên, tất cả các trường hợp của

class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
1 đang truy cập và sửa đổi cùng một danh sách trong
class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
8 mà không cần tự tạo các thuộc tính
In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
7 trong các không gian tên của chúng.

Chúng tôi có thể hiểu được điều này bằng cách sử dụng bài tập; Đó là, thay vì khai thác danh sách đột biến, chúng tôi có thể gán các đối tượng

class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
1 của chúng tôi để có danh sách riêng của chúng, như sau:

In [15]: MyClass.__dict__.get('attr', None)
Out[15]: 'attr value'
5

Trong trường hợp này, chúng tôi đã thêm

class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var
1, vì vậy
class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var
2 ban đầu không thay đổi.

Thật không may, điều này đòi hỏi người dùng

class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
1 có kiến ​​thức sâu sắc về các biến của nó và chắc chắn dễ bị lỗi. Theo một nghĩa nào đó, chúng tôi đã giải quyết các triệu chứng hơn là nguyên nhân. Chúng tôi thích một cái gì đó là chính xác bằng cách xây dựng.

Giải pháp cá nhân của tôi: Nếu bạn chỉ sử dụng một biến lớp để gán giá trị mặc định cho biến thể hiện Python sẽ sử dụng các giá trị có thể thay đổi. Trong trường hợp này, mọi trường hợp của

class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
1 sẽ ghi đè
class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var
5 với thuộc tính cá thể riêng của nó, do đó, sử dụng một danh sách trống làm mặc định đã dẫn đến một lỗi nhỏ dễ bị bỏ qua. Thay vì những điều trên, chúng ta cũng có thể làm được:don’t use mutable values. In this case, every instance of
class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
1 was going to override
class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var
5 with its own instance attribute eventually, so using an empty list as the default led to a tiny bug that was easily overlooked. Instead of the above, we could’ve either:

  1. Bị mắc kẹt trong các thuộc tính thể hiện hoàn toàn, như đã được chứng minh trong phần giới thiệu.
  2. Tránh sử dụng danh sách trống (giá trị có thể thay đổi) như mặc định của chúng tôi:

    In [15]: MyClass.__dict__.get('attr', None)
    Out[15]: 'attr value'
    
    6

    Tất nhiên, chúng tôi phải xử lý trường hợp

    class MyClass(object):
        class_var = 1
    
        def __init__(self, i_var):
            self.i_var = i_var
    
    6 một cách thích hợp, nhưng đó là một mức giá nhỏ để trả.

Vậy khi nào bạn nên sử dụng các thuộc tính lớp Python?

Các thuộc tính của lớp rất khó khăn, nhưng hãy để Lôi nhìn vào một vài trường hợp khi chúng có ích:

  1. Lưu trữ hằng số. Vì các thuộc tính lớp có thể được truy cập dưới dạng các thuộc tính của bản thân lớp, nên nó thường rất vui khi sử dụng chúng để lưu trữ các hằng số theo lớp, theo lớp học. Ví dụ:

    In [15]: MyClass.__dict__.get('attr', None)
    Out[15]: 'attr value'
    
    7
  2. Xác định các giá trị mặc định. Như một ví dụ tầm thường, chúng tôi có thể tạo một danh sách giới hạn (nghĩa là, một danh sách chỉ có thể giữ một số phần tử nhất định hoặc ít hơn) và chọn có nắp mặc định là 10 mục:

    In [15]: MyClass.__dict__.get('attr', None)
    Out[15]: 'attr value'
    
    8

    Sau đó, chúng tôi cũng có thể tạo các phiên bản với các giới hạn cụ thể của riêng họ, bằng cách gán cho thuộc tính phiên bản ____ ____67.

    In [15]: MyClass.__dict__.get('attr', None)
    Out[15]: 'attr value'
    
    9

    Điều này chỉ có ý nghĩa nếu bạn muốn thể hiện điển hình của mình là

    class Service(object):
        data = []
    
        def __init__(self, other_data):
            self.other_data = other_data
        ...
    
    7 chỉ giữ 10 yếu tố hoặc ít hơn nếu bạn đưa ra tất cả các giới hạn khác nhau của bạn, thì
    class MyClass(object):
        class_var = 1
    
        def __init__(self, i_var):
            self.i_var = i_var
    
    7 sẽ là một biến thể hiện. (Tuy nhiên, hãy nhớ: Hãy cẩn thận khi sử dụng các giá trị có thể thay đổi làm mặc định của bạn.)

  3. Theo dõi tất cả dữ liệu trên tất cả các trường hợp của một lớp nhất định. Đây là loại cụ thể, nhưng tôi có thể thấy một kịch bản mà bạn có thể muốn truy cập một phần dữ liệu liên quan đến mọi trường hợp hiện có của một lớp nhất định.

    Để làm cho kịch bản trở nên cụ thể hơn, hãy để nói rằng chúng tôi có một lớp

    foo = MyClass(2)
    bar = MyClass(3)
    
    foo.class_var, foo.i_var
    ## 1, 2
    bar.class_var, bar.i_var
    ## 1, 3
    MyClass.class_var ## <— This is key
    ## 1
    
    0 và mỗi người đều có
    foo = MyClass(2)
    bar = MyClass(3)
    
    foo.class_var, foo.i_var
    ## 1, 2
    bar.class_var, bar.i_var
    ## 1, 3
    MyClass.class_var ## <— This is key
    ## 1
    
    1. Chúng tôi muốn theo dõi tất cả các tên đã được sử dụng. Một cách tiếp cận có thể là lặp lại danh sách các đối tượng của Trình thu thập rác, nhưng nó đơn giản hơn để sử dụng các biến lớp.

    Lưu ý rằng, trong trường hợp này,

    foo = MyClass(2)
    bar = MyClass(3)
    
    foo.class_var, foo.i_var
    ## 1, 2
    bar.class_var, bar.i_var
    ## 1, 3
    MyClass.class_var ## <— This is key
    ## 1
    
    2 sẽ chỉ được truy cập dưới dạng biến lớp, do đó mặc định có thể thay đổi được chấp nhận.

    In [12]: class MyClass(object):
    ...:         @staticmethod
    ...:         def the_static_method(x):
    ...:             print(x)
    
    
    In [15]: MyClass.the_static_method(2)
    Out[15]: 2
    
    0

    Chúng tôi thậm chí có thể sử dụng mẫu thiết kế này để theo dõi tất cả các trường hợp hiện có của một lớp nhất định, thay vì chỉ một số dữ liệu liên quan.

    In [12]: class MyClass(object):
    ...:         @staticmethod
    ...:         def the_static_method(x):
    ...:             print(x)
    
    
    In [15]: MyClass.the_static_method(2)
    Out[15]: 2
    
    1
  4. Hiệu suất (sắp xếp xem bên dưới).

Under-the-hood

Lưu ý: Nếu bạn đang lo lắng về hiệu suất ở cấp độ này, bạn có thể không muốn sử dụng Python ngay từ đầu, vì sự khác biệt sẽ theo thứ tự của một phần mười của một mili giây nhưng vẫn vui khi chọc một chút, và giúp minh họa cho lợi ích. If you’re worrying about performance at this level, you might not want to be use Python in the first place, as the differences will be on the order of tenths of a millisecond—but it’s still fun to poke around a bit, and helps for illustration’s sake.

Hãy nhớ lại rằng một không gian tên lớp học được tạo ra và điền vào thời điểm định nghĩa lớp học. Điều đó có nghĩa là chúng tôi chỉ thực hiện một bài tập khác với một biến cho một biến nhất định, trong khi các biến thể hiện phải được gán mỗi khi một phiên bản mới được tạo. Hãy để lấy một ví dụ.

In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
2

Chúng tôi chỉ định cho

foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1
3 chỉ một lần, nhưng
foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1
4 trên mỗi cuộc gọi đến
foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1
5.

Để làm bằng chứng nữa, hãy để sử dụng Python Disassembler:

In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
3

Khi chúng ta nhìn vào mã byte, một lần nữa rõ ràng là

foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1
6 phải thực hiện hai bài tập, trong khi
foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1
7 chỉ làm một.

Trong thực tế, điều này đạt được thực sự trông như thế nào? Tôi sẽ là người đầu tiên thừa nhận rằng các bài kiểm tra thời gian phụ thuộc rất nhiều vào các yếu tố thường không thể kiểm soát và sự khác biệt giữa chúng thường khó giải thích chính xác.

Tuy nhiên, tôi nghĩ rằng những đoạn trích nhỏ này (chạy với mô -đun thời gian Python) giúp minh họa sự khác biệt giữa các biến lớp và phiên bản, vì vậy tôi đã bao gồm chúng.

Lưu ý: Tôi đã trên một MacBook Pro với OS X 10.8.5 và Python 2.7.2.

Khởi tạo

In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
4

Việc khởi tạo

foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1
8 nhanh hơn trong một giây, do đó, sự khác biệt ở đây dường như có ý nghĩa thống kê.

Vậy tại sao điều này là trường hợp? Một lời giải thích đầu cơ: Chúng tôi thực hiện hai bài tập trong

foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1
6, nhưng chỉ một trong
foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1
7.

Phân công

In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
5

Lưu ý: Không có cách nào để chạy lại mã thiết lập của bạn trên mỗi thử nghiệm với thời gian, vì vậy chúng tôi phải tái cấu trúc biến của chúng tôi trong thử nghiệm của chúng tôi. Dòng thời gian thứ hai đại diện cho thời gian trên với thời gian khởi tạo được tính toán trước đó được khấu trừ.

Từ những điều trên, có vẻ như

class MyClass(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
MyClass.class_var
## 1
1 chỉ mất khoảng 60% miễn là
foo = MyClass(2)
bar = MyClass(3)

foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
MyClass.class_var ## <— This is key
## 1
8 để xử lý các bài tập.

Tại sao điều này là trường hợp? Một lời giải thích đầu cơ: Khi chúng ta gán cho

class MyClass(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
MyClass.class_var
## 1
3, trước tiên chúng ta nhìn vào không gian tên trường hợp (
class MyClass(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
MyClass.class_var
## 1
4), không tìm thấy
class MyClass(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
MyClass.class_var
## 1
5, và sau đó nhìn vào không gian tên lớp (
class MyClass(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
MyClass.class_var
## 1
6), sau đó thực hiện nhiệm vụ thích hợp. Khi chúng tôi gán cho
class MyClass(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
MyClass.class_var
## 1
7, chúng tôi thực hiện một nửa số lần tra cứu, khi chúng tôi gán ngay lập tức cho không gian tên cá thể (
class MyClass(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
MyClass.class_var
## 1
8).

Tóm lại, mặc dù những lợi ích hiệu suất này đã giành được vấn đề trong thực tế, những thử nghiệm này rất thú vị ở cấp độ khái niệm. Nếu bất cứ điều gì, tôi hy vọng những khác biệt này giúp minh họa sự khác biệt cơ học giữa các biến lớp và trường hợp.

Tóm lại là

Các thuộc tính lớp dường như được sử dụng trong Python; Rất nhiều lập trình viên có những ấn tượng khác nhau về cách họ làm việc và tại sao chúng có thể hữu ích.

My Take: Các biến lớp Python có vị trí của họ trong trường của mã tốt. Khi được sử dụng một cách chăm sóc, họ có thể đơn giản hóa mọi thứ và cải thiện khả năng đọc. Nhưng khi bất cẩn ném vào một lớp học nhất định, họ chắc chắn sẽ vấp ngã bạn.

Phụ lục: Biến trường hợp riêng tư

Một điều tôi muốn bao gồm nhưng didn có một điểm vào tự nhiên

Python không có các biến riêng tư để nói, nhưng một mối quan hệ thú vị khác giữa việc đặt tên lớp và thể hiện đi kèm với tên mang tên.

Trong hướng dẫn theo phong cách Python, nó đã nói rằng các biến giả-tư nhân nên được đặt trước với một dấu gạch dưới kép: ‘__. Đây không chỉ là một dấu hiệu cho những người khác rằng biến của bạn có nghĩa là được đối xử riêng tư, mà còn là một cách để ngăn chặn quyền truy cập vào nó, các loại. Ở đây, ý tôi là:

In [12]: class MyClass(object):
...:         @staticmethod
...:         def the_static_method(x):
...:             print(x)


In [15]: MyClass.the_static_method(2)
Out[15]: 2
6

Hãy nhìn vào đó: Thuộc tính thể hiện

class MyClass(object):
    ## No need for dot syntax
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var

## Need dot syntax as we've left scope of class namespace
MyClass.class_var
## 1
9 được tự động có tiền tố với tên lớp để mang lại
foo = MyClass(2)

## Finds i_var in foo's instance namespace
foo.i_var
## 2

## Doesn't find class_var in instance namespace…
## So look's in class namespace (MyClass.__dict__)
foo.class_var
## 1
0.

Mặc dù vẫn có thể giải quyết được và có thể sử dụng

foo = MyClass(2)

## Finds i_var in foo's instance namespace
foo.i_var
## 2

## Doesn't find class_var in instance namespace…
## So look's in class namespace (MyClass.__dict__)
foo.class_var
## 1
1, tên này là một phương tiện để tạo ra một biến riêng tư vì nó ngăn bạn và những người khác truy cập nó một cách tình cờ hoặc thông qua sự thiếu hiểu biết.

Chỉnh sửa: Như Pedro Werneck đã chỉ ra, hành vi này phần lớn nhằm giúp đỡ với các lớp con. Trong hướng dẫn kiểu PEP 8, họ xem nó là phục vụ hai mục đích: (1) ngăn chặn các lớp con truy cập vào một số thuộc tính nhất định và (2) ngăn chặn các cuộc đụng độ không gian tên trong các lớp con này. Mặc dù hữu ích, biến đổi biến đổi không nên được coi là một lời mời viết mã với sự phân biệt công ty tư nhân giả định, chẳng hạn như có trong Java.

Một thuộc tính lớp có thể được sử dụng mà không cần ví dụ trong Python không?

Mặc dù bạn có thể truy cập các thuộc tính lớp bằng cách sử dụng một thể hiện, nhưng không an toàn khi làm như vậy. Trong Python, trường hợp của một lớp được gọi bằng từ khóa. Sử dụng từ khóa này, bạn có thể truy cập không chỉ tất cả các thuộc tính thể hiện mà cả các thuộc tính lớp.you can access class attributes using an instance it's not safe to do so. In python, the instance of a class is referred to by the keyword self. Using this keyword you can access not only all instance attributes but also the class attributes.

Làm thế nào để bạn truy cập một thuộc tính lớp trong Python?

Các thuộc tính của một lớp cũng có thể được truy cập bằng các phương thức và hàm tích hợp sau: getattr ()-hàm này được sử dụng để truy cập thuộc tính của đối tượng.HasAttr () - Hàm này được sử dụng để kiểm tra xem thuộc tính có tồn tại hay không.setAttr () - Hàm này được sử dụng để đặt thuộc tính.getattr() – This function is used to access the attribute of object. hasattr() – This function is used to check if an attribute exist or not. setattr() – This function is used to set an attribute.

Làm thế nào để bạn truy cập thuộc tính riêng tư trong Python?

Trong Python, không có sự tồn tại của các phương thức riêng tư không thể truy cập ngoại trừ bên trong một lớp.Tuy nhiên, để xác định tiền tố phương thức riêng tư tên thành viên với Double Undercore, __.Lưu ý: Phương thức __init__ là một hàm tạo và chạy ngay khi một đối tượng của một lớp được khởi tạo.there is no existence of Private methods that cannot be accessed except inside a class. However, to define a private method prefix the member name with the double underscore “__”. Note: The __init__ method is a constructor and runs as soon as an object of a class is instantiated.

Làm thế nào để bạn sửa đổi một thuộc tính lớp trong Python?

Nhưng hãy cẩn thận, nếu bạn muốn thay đổi thuộc tính lớp, bạn phải làm điều đó với ký hiệu ClassName.AttributEname.Nếu không, bạn sẽ tạo một biến thể hiện mới.ClassName. AttributeName. Otherwise, you will create a new instance variable.