Các lớp Python được lưu trữ ở đâu?

Cấp phát bộ nhớ có thể được định nghĩa là cấp phát một khối không gian trong bộ nhớ máy tính cho một chương trình. Trong Python, phương thức cấp phát và hủy bỏ bộ nhớ là tự động vì các nhà phát triển Python đã tạo bộ thu gom rác cho Python để người dùng không phải thực hiện thu gom rác thủ công

Thu gom rác thải

Thu gom rác là một quá trình trong đó trình thông dịch giải phóng bộ nhớ khi không sử dụng để cung cấp bộ nhớ cho các đối tượng khác
Giả sử trường hợp không có tham chiếu nào trỏ đến một đối tượng trong bộ nhớ i. e. vì vậy nó không được sử dụng, máy ảo có bộ thu gom rác tự động xóa đối tượng đó khỏi bộ nhớ heap

Ghi chú. Để biết thêm về thu gom rác, bạn có thể tham khảo bài viết này

Đếm tham khảo

Đếm tham chiếu hoạt động bằng cách đếm số lần một đối tượng được tham chiếu bởi các đối tượng khác trong hệ thống. Khi các tham chiếu đến một đối tượng bị xóa, số lượng tham chiếu cho một đối tượng sẽ giảm đi. Khi số lượng tham chiếu trở thành 0, đối tượng được hủy bỏ

Ví dụ: Giả sử có hai hoặc nhiều biến có cùng giá trị, vì vậy, máy ảo Python làm gì, thay vì tạo một đối tượng khác có cùng giá trị trong vùng riêng tư, nó thực sự làm cho biến thứ hai trỏ đến điểm ban đầu . Do đó, trong trường hợp của các lớp, việc có một số tham chiếu có thể chiếm một lượng lớn không gian trong bộ nhớ, trong trường hợp như vậy, việc đếm tham chiếu rất có lợi để duy trì bộ nhớ khả dụng cho các đối tượng khác

Thí dụ




# Literal 9 is an object 

b= 9

a= 4

   

# Reference count of object 9  

# becomes 0 and reference count

b0

b1

b= 4

Phân bổ bộ nhớ trong Python

Có hai phần của bộ nhớ

  • ngăn xếp bộ nhớ
  • bộ nhớ đống

Các phương thức/cuộc gọi phương thức và các tham chiếu được lưu trữ trong bộ nhớ ngăn xếp và tất cả các đối tượng giá trị được lưu trữ trong một đống riêng

Công việc của bộ nhớ ngăn xếp

Việc phân bổ xảy ra trên các khối bộ nhớ liền kề. Chúng tôi gọi đó là cấp phát bộ nhớ ngăn xếp vì việc cấp phát xảy ra trong ngăn xếp lệnh gọi hàm. Kích thước của bộ nhớ được phân bổ được trình biên dịch biết và bất cứ khi nào một hàm được gọi, các biến của nó sẽ nhận được bộ nhớ được phân bổ trên ngăn xếp

Đó là bộ nhớ chỉ cần thiết bên trong một lệnh gọi hàm hoặc phương thức cụ thể. Khi một chức năng được gọi, nó sẽ được thêm vào ngăn xếp cuộc gọi của chương trình. Bất kỳ phép gán bộ nhớ cục bộ nào, chẳng hạn như khởi tạo biến bên trong các chức năng cụ thể, được lưu trữ tạm thời trên ngăn lệnh gọi hàm, nơi nó sẽ bị xóa sau khi hàm trả về và ngăn xếp lệnh gọi chuyển sang tác vụ tiếp theo. Việc phân bổ này vào một khối bộ nhớ liền kề được trình biên dịch xử lý bằng cách sử dụng các thường trình được xác định trước và các nhà phát triển không cần phải lo lắng về điều đó

Thí dụ




b5 b6

b7

b8b9

b8=1

b8a= =5

b8b= =9

b891= 93

Công việc của bộ nhớ Heap

Bộ nhớ được phân bổ trong quá trình thực hiện các hướng dẫn được viết bởi các lập trình viên. Lưu ý rằng tên heap không liên quan gì đến cấu trúc dữ liệu heap. Nó được gọi là heap vì nó là một đống không gian bộ nhớ có sẵn cho các lập trình viên để cấp phát và hủy cấp phát. Các biến cần thiết bên ngoài các cuộc gọi phương thức hoặc chức năng hoặc được chia sẻ trong nhiều chức năng trên toàn cầu được lưu trữ trong bộ nhớ Heap

“Mọi thứ trong Python đều là đối tượng” đã trở thành một điệp khúc phổ biến trong cộng đồng Python. Đối tượng là gì? . Một đối tượng là một thể hiện của một lớp. Ví dụ: chuỗi là thể hiện của lớp str

# Creating a string variable
>>> device_type = "switch"
# device_type is an instance of the str class
>>> type[device_type]

>>>

Bản thân các lớp là thể hiện của

# Creating a class object normally
>>> class Cisco:
...     vendor = "cisco"
...
>>> Cisco

>>> Cisco.vendor
'cisco'
>>> isinstance[Cisco, type]
True
# Creating a class object explicitly from type
>>> Arista = type["Arista", [], {"vendor": "arista"}]
>>> Arista

>>> Arista.vendor
'arista'
>>>
0

# Creating a class object normally
>>> class Cisco:
...     vendor = "cisco"
...
>>> Cisco

>>> Cisco.vendor
'cisco'
>>> isinstance[Cisco, type]
True
# Creating a class object explicitly from type
>>> Arista = type["Arista", [], {"vendor": "arista"}]
>>> Arista

>>> Arista.vendor
'arista'
>>>

Ngoài việc là một thể hiện của một lớp, các đối tượng bao gồm các thuộc tính xác định trạng thái và hành vi. Người ta thường coi các thuộc tính trạng thái là thuộc tính dữ liệu hoặc biến và các hành vi được gọi là phương thức. Các lớp dựng sẵn của Python thường có nhiều phương thức, nhưng không có thuộc tính dữ liệu. Lớp str cung cấp các phương thức cho

  • Thao tác với chuỗi [viết hoa, định dạng, v.v. ]
  • Tìm thông tin về chuỗi [bắt đầu bằng, không phải là số, v.v. ]
  • Phân đoạn chuỗi [phân vùng, tách, v.v. ]

>>> example = "this is a string"
# Capitalize the first letter of each word 
>>> example.title[]
'This Is A String'
# Count the number of times the letter i appears
>>> example.count["i"]
3
# Convert the string into a list of words
>>> example.split[]
["this", "is", "a", "string"]

Các lớp tùy chỉnh thường có các thuộc tính dữ liệu lưu trữ thông tin về các đối tượng mà chúng bắt chước. Đối với một đối tượng đại diện cho một công tắc, một số thuộc tính dữ liệu ví dụ có thể là. mô-đun, thời gian hoạt động và khả năng tiếp cận. Một số phương pháp ví dụ có thể là. khởi động lại và ping

>>> switch = Arista[hostname="nyc-hq-rt1"]
# Example of a data attribute
>>> switch.uptime
'4 years, 3 days'
# Example of a method attribute
>>> ping_stats = switch.ping["10.1.1.1", 5]
'pinging 10.1.1.1 times 5'
>>> ping_stats
{
    'attempts': 5,
    'success': 5,
    'fail': 0,
    'messages': ['pinged 10.1.1.1 in 0.21ms', 'pinged 10.1.1.1 in 0.14ms', ...]
}
>>>

Thuộc tính dữ liệu

Thuộc tính dữ liệu được phân biệt giữa biến lớp và biến thể hiện. Các biến lớp gán các giá trị giống nhau cho tất cả các đối tượng của lớp. Biến thể hiện gán giá trị cho một thể hiện của lớp. Các biến lớp thường được sử dụng cho các trường siêu dữ liệu, chẳng hạn như

# Creating a class object normally
>>> class Cisco:
...     vendor = "cisco"
...
>>> Cisco

>>> Cisco.vendor
'cisco'
>>> isinstance[Cisco, type]
True
# Creating a class object explicitly from type
>>> Arista = type["Arista", [], {"vendor": "arista"}]
>>> Arista

>>> Arista.vendor
'arista'
>>>
1 trong ví dụ đầu tiên. Các biến thể hiện chứa nhiều thông tin thú vị hơn mà các phương thức đối tượng tác động lên. Sử dụng ví dụ trước, thuộc tính
# Creating a class object normally
>>> class Cisco:
...     vendor = "cisco"
...
>>> Cisco

>>> Cisco.vendor
'cisco'
>>> isinstance[Cisco, type]
True
# Creating a class object explicitly from type
>>> Arista = type["Arista", [], {"vendor": "arista"}]
>>> Arista

>>> Arista.vendor
'arista'
>>>
2 có thể được sử dụng trong báo cáo để xác định tất cả các công tắc không thể truy cập được. Lớp Cisco ở trên được xác định lại để tạo các biến thể hiện khi khởi tạo cho tên máy chủ, trạng thái kết nối và thông tin về khả năng tiếp cận

class Cisco:
    # Class variable
    vendor = "cisco"

    def __init__[self, hostname]:
        # Instance variables
        self.hostname = hostname
        self.connected = False
        ping_reachability = self.ping[hostname, 2]
        if ping_reachability["success"]:
            self.connect[]
            if self.connected:
                self.reachability = "authorized"
            else:
                self.reachability = "unauthorized"
        else:
            self.reachability = "unreachable"

    def connect[self]:
        ...
        self.connected = True if connected else False

    def ping[self, destination, count]:
        ...
        return {
            "attempts": count,
            "success": success_count,
            "fail": fail_count,
            "messages": [message for message in ping_results],
        }

Python sử dụng từ điển để lưu trữ các biến lớp và đối tượng. Các biến lớp chia sẻ cùng một từ điển trên tất cả các phiên bản của lớp và các biến thể hiện được lưu trữ trong một từ điển duy nhất cho mỗi phiên bản. Lớp dict được lưu trữ trong

# Creating a class object normally
>>> class Cisco:
...     vendor = "cisco"
...
>>> Cisco

>>> Cisco.vendor
'cisco'
>>> isinstance[Cisco, type]
True
# Creating a class object explicitly from type
>>> Arista = type["Arista", [], {"vendor": "arista"}]
>>> Arista

>>> Arista.vendor
'arista'
>>>
3 và điều này được tham chiếu trong một thể hiện với
# Creating a class object normally
>>> class Cisco:
...     vendor = "cisco"
...
>>> Cisco

>>> Cisco.vendor
'cisco'
>>> isinstance[Cisco, type]
True
# Creating a class object explicitly from type
>>> Arista = type["Arista", [], {"vendor": "arista"}]
>>> Arista

>>> Arista.vendor
'arista'
>>>
4. Ví dụ dict được lưu trữ trong
# Creating a class object normally
>>> class Cisco:
...     vendor = "cisco"
...
>>> Cisco

>>> Cisco.vendor
'cisco'
>>> isinstance[Cisco, type]
True
# Creating a class object explicitly from type
>>> Arista = type["Arista", [], {"vendor": "arista"}]
>>> Arista

>>> Arista.vendor
'arista'
>>>
5. Dưới đây là một số ví dụ cho thấy hai từ điển này hoạt động như thế nào

# View the class dict
>>> Cisco.__dict__
mappingproxy[{'vendor': 'cisco', ...}]
# Create two objects of the Cisco class
>>> rt1 = Cisco["nyc-hq-rt1"]
>>> rt2 = Cisco["nyc-dc-rt1"]
# Viewing the instance dict
>>> rt1.__dict__
{'hostname': 'nyc-hq-rt1', 'connected': True, 'reachability': 'authorized'}
# Reachability is an instance variable and can have different values across objects
>>> rt1.reachability
'authorized'
>>> rt2.reachability
'unreachable'
# The class dict is referenced within instances
>>> Cisco.__dict__ == rt1.__class__.__dict__
True
# Changing the vendor on the class is reflected on all instances
>>> Cisco.vendor = "CSCO"
>>> rt1.vendor
'CSCO'
>>> rt2.vendor
'CSCO'
>>>

Ưu tiên thuộc tính

Sự khác biệt này giữa các biến lớp và đối tượng rất quan trọng để hiểu hành vi truy cập thuộc tính của Python. Tra cứu thuộc tính tiêu chuẩn sử dụng thứ tự ưu tiên sau cho đến khi tìm thấy thuộc tính hoặc Lỗi được nêu ra

  1. Các thuộc tính được xác định trên ví dụ
  2. Các thuộc tính được định nghĩa trên lớp
  3. Các thuộc tính được định nghĩa trên các lớp kế thừa

Thực tế, điều này có nghĩa là việc ghi đè một thuộc tính lớp trên một thể hiện sẽ chỉ ảnh hưởng đến một thể hiện duy nhất chứ không ảnh hưởng đến các thể hiện khác

>>> rt1 = Cisco["nyc-hq-rt1"]
>>> rt2 = Cisco["nyc-dc-rt1"]
# rt1 and rt2 both have a value of "cisco" for the vendor attribute
>>> rt1.vendor == rt2.vendor == "cisco"
True
# rt1's instance dict does not have an attribute for `vendor`
>>> rt1.__dict__
{'hostname': 'nyc-hq-rt1', 'connected': True, 'reachability': 'authorized'}
>>> rt1.vendor = "Cisco"
>>> rt1.vendor
'Cisco'
# rt1's instance dict was updated with a `vendor` attribute
>>> rt1.__dict__
{'hostname': 'nyc-hq-rt1', 'connected': True, 'reachability': 'authorized', 'vendor': 'Cisco'}
# rt2's vendor attribute remains unchanged
>>> rt2.vendor
'cisco'

Thuộc tính có thể thay đổi

Phần trên thể hiện sự an toàn tích hợp được cung cấp khi đặt tên biến thể hiện va chạm với biến lớp. Tuy nhiên, hành vi này có thể có kết quả đáng ngạc nhiên khi các biến lớp trỏ đến các đối tượng có thể thay đổi [chẳng hạn như danh sách]. Lớp Arista được viết lại bên dưới để có một biến lớp xác định các mô-đun, với giá trị sử dụng danh sách cho khung mô-đun

class Arista:
    vendor = "arista"
    modules = ["7500E-48S", "DCS-7500E-SUP"]

>>> rt1 = Arista["nyc-hq-rt1"]
>>> rt2 = Arista["nyc-dc-rt1"]
>>> rt1.modules
["7500E-48S", "DCS-7500E-SUP"]
# Appending to rt2's `modules` attribute affects rt1
>>> rt2.modules.append["7500E-72S"]
>>> rt1.modules
["7500E-48S", "DCS-7500E-SUP", "7500E-72S"]
# Using the `+=` operator on rt2's `modules` attributed affects rt1
>>> rt2.modules += ["7500E-36Q"]
>>> rt1.modules
["7500E-48S", "DCS-7500E-SUP", "7500E-72S", "7500E-36Q"]
# Both modifications to rt2's `modules` attribute affect the class attribute
>>> Arista.modules
["7500E-48S", "DCS-7500E-SUP", "7500E-72S", "7500E-36Q"]
# All references to `modules` are the same shared object
>>> Arista.modules is rt1.modulues is rt2.modules
True
>>>

Phần kết luận

Hiểu cách các đối tượng hoạt động là rất quan trọng để làm việc với Python. Cơ bản để làm việc với các đối tượng là quản lý và sử dụng các thuộc tính dữ liệu. Thuộc tính dữ liệu có thể được tạo trên lớp hoặc trên từng thể hiện của lớp. Các thuộc tính cấp độ sơ thẩm có mức độ ưu tiên cao hơn các thuộc tính cấp độ lớp. Cuối cùng, khi tạo các thuộc tính trên một lớp, điều quan trọng là phải xem xét cách chúng sẽ được sử dụng và các thuộc tính có thể thay đổi đó có thể dẫn đến hành vi không mong muốn

Các lớp được lưu trữ trong Python như thế nào?

Cách Python lưu trữ các thuộc tính của lớp. Như tôi đã nói trước đó, các thuộc tính của lớp được sở hữu bởi chính lớp đó [i. e. , theo định nghĩa của nó]. Hóa ra, các lớp cũng đang sử dụng từ điển. Từ điển lớp cũng có thể được truy cập từ một thể hiện, sử dụng phương thức __class__ dunder [i. e. , xe ô tô.

Các lớp Python được lưu trữ trong bộ nhớ như thế nào?

Phân bổ bộ nhớ trong Python . stack memory and all the values objects are stored in a private heap.

Các định nghĩa lớp được lưu trữ trong Python ở đâu?

Nó được lưu trữ trong không gian tên của lớp [của nó là __dict__ ]. Lưu ý cách chức năng này sẽ đưa ra một ngoại lệ AttributeError nếu thuộc tính không được xác định trong thể hiện cũng như lớp. giống như con trăn.

Python có tệp lớp không?

Trong Python, một tệp được gọi là mô-đun . Một mô-đun có thể bao gồm nhiều lớp hoặc chức năng. Vì Python không chỉ là ngôn ngữ OO, nên không có quy tắc nào nói rằng, một tệp chỉ nên chứa một lớp.

Chủ Đề