Hướng dẫn how do you access class items in python? - làm thế nào để bạn truy cập các mục lớp trong python?

Câu trả lời, trong một vài từ

Trong ví dụ của bạn,

class Example(object):
    pass

Example.itsProblem = "problem"

e = Example()
e.itsSecondProblem = "problem"

print Example.itsProblem == e.itsSecondProblem 
9 là một biến cục bộ.

Bạn phải sử dụng

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 để đặt và nhận các biến thể hiện. Bạn có thể đặt nó trong phương thức
class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
1. Sau đó, mã của bạn sẽ là:

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

Nhưng nếu bạn muốn một biến lớp thực sự, thì hãy sử dụng trực tiếp tên lớp:

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)

Nhưng hãy cẩn thận với cái này, vì

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
2 được đặt tự động bằng
class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
3, nhưng hoàn toàn không phải là cùng một biến và có thể được thay đổi độc lập.

Một số giải thích

Trong Python, các biến có thể được tạo động. Do đó, bạn có thể làm như sau:

class Example(object):
    pass

Example.itsProblem = "problem"

e = Example()
e.itsSecondProblem = "problem"

print Example.itsProblem == e.itsSecondProblem 

bản in

ĐÚNG VẬY

Do đó, đó chính xác là những gì bạn làm với các ví dụ trước.

Thật vậy, trong Python, chúng tôi sử dụng

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 là
class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
5, nhưng nó còn nhiều hơn thế.
class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 là đối số đầu tiên cho bất kỳ phương thức đối tượng nào vì đối số đầu tiên luôn là tham chiếu đối tượng. Đây là tự động, cho dù bạn có gọi nó là
class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 hay không.

Có nghĩa là bạn có thể làm:

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

or:

class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

Nó giống hệt nhau. Đối số đầu tiên của bất kỳ phương thức đối tượng nào là đối tượng hiện tại, chúng tôi chỉ gọi nó là

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 là một quy ước. Và bạn chỉ thêm một biến cho đối tượng này, giống như cách bạn sẽ làm từ bên ngoài.

Bây giờ, về các biến lớp.

Khi bạn làm:

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)

Trước tiên, bạn sẽ nhận thấy chúng tôi đặt một biến lớp, sau đó chúng tôi truy cập một biến đối tượng (cá thể). Chúng tôi không bao giờ đặt biến đối tượng này nhưng nó hoạt động, làm thế nào là có thể?set a class variable, then we access an object (instance) variable. We never set this object variable but it works, how is that possible?

Chà, Python cố gắng để có được biến đối tượng trước, nhưng nếu không tìm thấy nó, sẽ cung cấp cho bạn biến lớp. CẢNH BÁO: Biến lớp được chia sẻ giữa các trường hợp và biến đối tượng thì không.

Để kết luận, không bao giờ sử dụng các biến lớp để đặt các giá trị mặc định thành các biến đối tượng. Sử dụng

class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
1 cho điều đó.

Cuối cùng, bạn sẽ biết rằng các lớp Python là những trường hợp và do đó chính các đối tượng, điều này mang lại cái nhìn sâu sắc mới để hiểu những điều trên. Hãy quay lại và đọc lại điều này sau, một khi bạn nhận ra điều đó.

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ố

class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 và một số
class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
1.

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 đó:
    class Example(object):
        def __init__(my_super_self):
            my_super_self.itsProblem = "problem"
    
    
    theExample = Example()
    print(theExample.itsProblem)
    
    2. 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 how do you access class items in python? - làm thế nào để bạn truy cập các mục lớp trong python?

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

class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 là thuộc tính lớp có giá trị
class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
4.

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,

class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
5 là thuộc tính lớp và
class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
6 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

class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
5 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ụ:

class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
8) hoặc làm biến cục bộ (ví dụ:
class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
9). Như một ví dụ cụ thể:

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
0

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

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 và
class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
1, 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ụ:

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
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:

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
2

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

Hướng dẫn how do you access class items in python? - làm thế nào để bạn truy cập các mục lớp trong python?

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ụ:

    class Example(object):
        itsProblem = "problem"
    
    
    theExample = Example()
    print(theExample.itsProblem)
    print (Example.itsProblem)
    
    3

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

    class Example(object):
        itsProblem = "problem"
    
    
    theExample = Example()
    print(theExample.itsProblem)
    
    2. . Sau đó, khi chúng tôi truy cập
    class Example(object):
        itsProblem = "problem"
    
    
    theExample = Example()
    print(theExample.itsProblem)
    
    5,
    class Example(object):
        def __init__(my_super_self):
            my_super_self.itsProblem = "problem"
    
    
    theExample = Example()
    print(theExample.itsProblem)
    
    5 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ụ:

    class Example(object):
        itsProblem = "problem"
    
    
    theExample = Example()
    print(theExample.itsProblem)
    print (Example.itsProblem)
    
    4

    Ở 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):
    data = []

    def __init__(self, other_data):
        self.other_data = other_data
    ...
4 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 (

class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
4) là giá trị mặc định cho
class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 và cho mỗi trường hợp
class Service(object):
    data = []

    def __init__(self, other_data):
        self.other_data = other_data
    ...
4 để 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):
    data = []

    def __init__(self, other_data):
        self.other_data = other_data
    ...
4 có một số đối số
class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
1, đó là tùy ý trong ví dụ này):

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
6

Đâ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):
    data = []

    def __init__(self, other_data):
        self.other_data = other_data
    ...
4 đều đ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
    ...
1 mà không tự tạo các thuộc tính
class Example(object):
    def __init__(my_super_self):
        my_super_self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
0 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):
    data = []

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

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
7

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

class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
4, vì vậy
class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
5 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):
    data = []

    def __init__(self, other_data):
        self.other_data = other_data
    ...
4 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):
    data = []

    def __init__(self, other_data):
        self.other_data = other_data
    ...
4 sẽ ghi đè
class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
8 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):
    data = []

    def __init__(self, other_data):
        self.other_data = other_data
    ...
4 was going to override
class Service(object):

    def __init__(self, other_data):
        self.data = []
        self.other_data = other_data
    ...
8 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:

    class Example(object):
        itsProblem = "problem"
    
    
    theExample = Example()
    print(theExample.itsProblem)
    print (Example.itsProblem)
    
    8

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

    class Service(object):
    
        def __init__(self, other_data):
            self.data = []
            self.other_data = other_data
        ...
    
    9 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ụ:

    class Example(object):
        itsProblem = "problem"
    
    
    theExample = Example()
    print(theExample.itsProblem)
    print (Example.itsProblem)
    
    9
  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:

    class Example(object):
        pass
    
    Example.itsProblem = "problem"
    
    e = Example()
    e.itsSecondProblem = "problem"
    
    print Example.itsProblem == e.itsSecondProblem 
    
    0

    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 ____ ____80.

    class Example(object):
        pass
    
    Example.itsProblem = "problem"
    
    e = Example()
    e.itsSecondProblem = "problem"
    
    print Example.itsProblem == e.itsSecondProblem 
    
    1

    Điều này chỉ có ý nghĩa nếu bạn sẽ muốn ví dụ điển hình của mình là

    class Service(object):
        data = []
    
        def __init__(self, other_data):
            self.other_data = other_data
        ...
    
    0 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
    
    0 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 cụ thể hơn, hãy để nói rằng chúng tôi có một lớp

    class MyClass(object):
        class_var = 1
    
        def __init__(self, i_var):
            self.i_var = i_var
    
    3 và mỗi người đều có
    class MyClass(object):
        class_var = 1
    
        def __init__(self, i_var):
            self.i_var = i_var
    
    4. 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,

    class MyClass(object):
        class_var = 1
    
        def __init__(self, i_var):
            self.i_var = i_var
    
    5 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.

    class Example(object):
        pass
    
    Example.itsProblem = "problem"
    
    e = Example()
    e.itsSecondProblem = "problem"
    
    print Example.itsProblem == e.itsSecondProblem 
    
    2

    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.

    class Example(object):
        pass
    
    Example.itsProblem = "problem"
    
    e = Example()
    e.itsSecondProblem = "problem"
    
    print Example.itsProblem == e.itsSecondProblem 
    
    3
  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ụ.

class Example(object):
    pass

Example.itsProblem = "problem"

e = Example()
e.itsSecondProblem = "problem"

print Example.itsProblem == e.itsSecondProblem 
4

Chúng tôi gán cho

class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var
6 chỉ một lần, nhưng
class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var
7 trên mỗi cuộc gọi đến
class Example(object):
    def __init__(self):
        self.itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
1.

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

class Example(object):
    pass

Example.itsProblem = "problem"

e = Example()
e.itsSecondProblem = "problem"

print Example.itsProblem == e.itsSecondProblem 
5

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

class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var
9 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
0 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

class Example(object):
    pass

Example.itsProblem = "problem"

e = Example()
e.itsSecondProblem = "problem"

print Example.itsProblem == e.itsSecondProblem 
6

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

class MyClass(object):
    class_var = 1

    def __init__(self, i_var):
        self.i_var = i_var
9, 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
0.

Phân công

class Example(object):
    pass

Example.itsProblem = "problem"

e = Example()
e.itsSecondProblem = "problem"

print Example.itsProblem == e.itsSecondProblem 
7

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ư

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 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
1 để 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

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, trước tiên chúng ta nhìn vào không gian tên trường hợ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
7), không tìm thấ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
8, và sau đó xem trong không gian tên 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
9), sau đó thực hiện nhiệm vụ thích hợp. Khi chúng tôi gán cho
class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
00, 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 thể hiện (
class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
01).

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à:

class Example(object):
    pass

Example.itsProblem = "problem"

e = Example()
e.itsSecondProblem = "problem"

print Example.itsProblem == e.itsSecondProblem 
8

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

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
02 được tự động có tiền tố với tên lớp để mang lại
class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
03.

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

class Example(object):
    itsProblem = "problem"


theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
04, 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.

Làm thế nào để bạn truy cập các biến lớp?

Truy cập các biến lớp Chúng tôi có thể truy cập các biến tĩnh bằng tên lớp hoặc theo tham chiếu đối tượng, nhưng nên sử dụng tên lớp.Truy cập bên trong hàm tạo bằng cách sử dụng tham số tự hoặc tên lớp.Truy cập từ bên ngoài lớp bằng cách sử dụng tham chiếu đối tượng hoặc tên lớp.either by class name or by object reference, but it is recommended to use the class name. Access inside the constructor by using either self parameter or class name. Access from outside of class by using either object reference or class name.

Làm thế nào để bạn truy cập các biến lớp bên ngoài lớp trong Python?

Các biến được xác định bên ngoài lớp có thể được truy cập bởi bất kỳ lớp hoặc bất kỳ phương thức nào trong lớp bằng cách chỉ viết tên biến.by just writing the variable name.

Làm thế nào để bạn sử dụng các lớp học trong Python?

Một lớp giống như một hàm tạo đối tượng hoặc "bản thiết kế" để tạo các đối tượng ...
Tạo một lớp học.Để tạo một lớp, hãy sử dụng lớp từ khóa: ....
Tạo đối tượng.Bây giờ chúng ta có thể sử dụng lớp có tên MyClass để tạo các đối tượng: ....
Tham số tự.....
Sửa đổi thuộc tính đối tượng.....
Xóa thuộc tính đối tượng.....
Xóa đối tượng ..