Python dict vào thể hiện của lớp

Thông thường, để truy cập các giá trị trong từ điển, tôi cần đảm bảo và tham khảo rất cụ thể tất cả các giá trị phù hợp không có lỗi chính tả. Nếu tôi muốn lấy giá trị được lưu trong khóa n1, tôi cần nhập chính xác

my_dict['nested_value']['n1']

Vì hầu hết thời gian tôi làm việc trong Jupyter, nên tôi tận dụng lợi thế của việc hoàn thành và xem xét nội tâm để khám phá các thuộc tính và tránh lỗi chính tả. Từ điển Python không giúp ích nhiều cho việc này, nhưng các Đối tượng Python thì có. Điều này đặt ra một cách hợp lý câu hỏi, làm thế nào để tạo hệ thống phân cấp đối tượng lồng nhau để tôi có thể truy cập cùng một giá trị bằng cú pháp dấu chấm

my_dict.nested_value.n1

Mặc dù với các từ điển đơn giản, đây không phải là vấn đề lớn, nhưng khi làm việc với các phản hồi từ các điểm cuối REST, các thông báo JSON được trả về có thể rất lớn. Truy cập dễ dàng hơn vào tất cả các thuộc tính làm cho cuộc sống dễ dàng hơn rất nhiều. Khai báo đối tượng nhỏ sau đây có thể được sử dụng để chuyển đổi các từ điển được lồng sâu thành các đối tượng lồng nhau

class DictObj:
    def __init__[self, in_dict:dict]:
    	assert isinstance[in_dict, dict]
        for key, val in in_dict.items[]:
            if isinstance[val, [list, tuple]]:
               setattr[self, key, [DictObj[x] if isinstance[x, dict] else x for x in val]]
            else:
               setattr[self, key, DictObj[val] if isinstance[val, dict] else val]

Điều này giúp việc tìm hiểu các phản hồi JSON sâu từ các điểm cuối REST dễ dàng hơn rất nhiều. Bắt đầu đủ đơn giản, từ điển trên được chuyển đổi thành một đối tượng lồng nhau

my_obj = DictObt[my_dict]

Sau đó, việc truy cập các thuộc tính đơn giản như sử dụng cú pháp dấu chấm

my_obj.nested_value.n1

Vì đây là điều mà tôi thường xuyên gặp phải khi đào sâu vào JSON từ các phản hồi REST, nên tôi sẽ sử dụng Luồng thời gian thực của USGS làm ví dụ trong thế giới thực

import requests

url = '//waterservices.usgs.gov/nwis/iv/'
params = {
    'format': 'json',
    'sites': '12080010',
    'parameterCd': '00060',
    'siteStatus': 'all'
}

# retrieve the most recent real time streamflow observations
res = requests.get[url, params=params]

# convert the json body into a dictionary
res_json = res.json[]

# convert the json to a nested object
res_obj = DictObj[res_json]

# dig deep into the response to get the most recent [last in list] value
str_obs = res_obj.value.timeSeries[-1].values[-1].value[-1].value

# since stuck as a string, convert to an integer, and done!
int_obs = int[str_obs]

Thủ thuật nhỏ này đã giúp cuộc sống của tôi dễ dàng hơn rất nhiều khi xử lý JSON rối rắm quay trở lại từ các điểm cuối REST. Hy vọng rằng, nó cũng làm cho cuộc sống của bạn dễ dàng hơn một chút

“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ệnh của lớp đượ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

Làm cách nào để chuyển đổi dict sang lớp Python?

Chúng tôi đang gọi một hàm ở đây là Dict2Class lấy từ điển của chúng tôi làm đầu vào và chuyển đổi nó thành lớp . Sau đó, chúng tôi lặp lại từ điển của mình bằng cách sử dụng hàm setattr[] để thêm từng khóa làm thuộc tính cho lớp. setattr[] được sử dụng để gán giá trị cho thuộc tính đối tượng.

__ dict __ của một lớp và hoặc thể hiện của một lớp là gì và nó chứa những gì?

__dict__ là Từ điển hoặc đối tượng ánh xạ khác được sử dụng để lưu trữ các thuộc tính [có thể ghi] của đối tượng . Hay nói một cách đơn giản, mọi đối tượng trong python đều có một thuộc tính được ký hiệu là __dict__. Và đối tượng này chứa tất cả các thuộc tính được xác định cho đối tượng.

Từ điển mẫu Python là gì?

Một thể hiện dict chứa tham chiếu đến tất cả các đối tượng và giá trị được gán cho thể hiện và dict cấp độ lớp chứa tất cả các tham chiếu tại lớp . Lấy ví dụ sau. >>> hạng A[đối tượng]. . def foo[bản thân, thanh]. .

Khóa dict Python có thể là một đối tượng không?

Khóa từ điển phải là đối tượng bất biến . Một giá trị từ điển có thể là bất kỳ đối tượng nào.

Chủ Đề