"John Wilson"
tin tức. người đưa thư. 1051631814. @python. tổ chức.
> Cho lớp này.
>
> Chủ sở hữu lớp[tuple].
> def __init__[bản thân, *giá trị].
> bộ. __init__[self, values]
>
>
> Khi tôi cố gắng tạo một phiên bản.
>
> Người giữ [1, 2]
>
> Tôi hiểu.
>
> TypeError. tuple[] nhận tối đa 1 đối số [2 đối số đã cho]
>
> Có vẻ như hàm tạo của siêu lớp đang được gọi
rather than
> the __init__ method on Holder.
>
> Rõ ràng là tôi đang thiếu thứ gì đó ở đây. Tôi có phải cung cấp phương thức __new__
không?
> Mọi trợ giúp đều được đánh giá cao.
Bởi vì các bộ dữ liệu là bất biến, nên người ta không thể thay đổi chúng trong phương thức init
, ngay cả khi đặt các giá trị ban đầu. Vì vậy, như bạn nghi ngờ
, chúng được khởi tạo trong phương thức __new__ từ một trình tự.
Đây là nguồn gốc của ngoại lệ [xem bên dưới]. tuple. __init__ nên
không nên.
>>> Chủ sở hữu lớp [tuple].
. def __init__[bản thân, *giá trị].
. print "Đã nhập chủ sở hữu"
.
>>> Người giữ [1,2]
Truy nguyên [lần gọi gần đây nhất].
Tệp "", dòng 1, trong ?
LoạiLỗi. tuple[] nhận tối đa 1 đối số [2 đối số đã cho]
# khởi tạo không được nhập
>>> Chủ sở hữu [[1,2]]
Chủ sở hữu khởi tạo được nhập
[1, 2]
Người nắm giữ trong khi. __init__[] không thể sửa đổi giá trị của self, nó *có thể* thêm
thuộc tính [điều này làm tôi hơi ngạc nhiên] để nó có thể sử dụng.
>>> Chủ sở hữu lớp [tuple].
. def __init__[self, seq].
. bản thân. y = 1
.
>>> a=Holder[[1,2]]
>>> a. y
1
Tôi không biết bạn có thể làm gì hơn trong phương pháp __new__
Terry J. lau sậy
Tôi sẽ gọi lớp có __init__
là lớp Python “thông thường” trong bài viết này. Xin vui lòng cho tôi biết nếu có một tên chính thức cho nó. Nếu bạn muốn đi sâu vào Named Tuple và Dataclass, hãy xem các liên kết tham khảo
Mỗi giao dịch thanh toán có người gửi, người nhận, ngày và số tiền. Nếu tôi sử dụng lớp Python thông thường, nó có thể trông giống như thế này
Giao dịch. pyNó rất đơn giản. Nhưng thành thật mà nói, đó là rất nhiều mã, ít nhất là rất nhiều dòng. Trong trường hợp sử dụng mà tôi đang sử dụng các bản ghi giao dịch theo thời gian thực từ một nguồn [e. g. Kafka], tôi không muốn linh hoạt sửa đổi bản ghi. Làm thế nào tôi có thể đạt được điều đó một cách sạch sẽ hơn?
Tuple được đặt tên
Tuple được đặt tên có thể là một sự thay thế tuyệt vời ở đây để xây dựng một lớp. Tuple được đặt tên về cơ bản là một phần mở rộng của kiểu dữ liệu Tuple tích hợp sẵn trong Python. Tuple Python là một cấu trúc dữ liệu đơn giản để nhóm các đối tượng với các loại khác nhau. Tính năng xác định của nó là không thay đổi
Một đối tượng bất biến là một đối tượng mà trạng thái của nó không thể thay đổi được sau khi nó được tạo ra
Trong Python, các kiểu bất biến là int, float, bool, str, tuple và unicode
Tuy nhiên, một nhược điểm của loại bộ dữ liệu tích hợp là nó đặt rất nhiều trách nhiệm lên người lập trình. Khi bạn truy cập một thuộc tính của bộ dữ liệu tích hợp, bạn cần biết chỉ mục của nó. Nó sẽ gây ra một số nhầm lẫn nếu bạn đang phát triển một thư viện sẽ được sử dụng bởi hàng nghìn người dùng
Một cách khả thi khác là sử dụng từ điển tích hợp sẵn, như {"sender":"","receiver":"","date":"","amount":""}
. Nhưng vấn đề ở đây là bạn cần đánh vần đúng tên các phím. Và nó hoàn toàn không phải là một lớp học
Chúng ta có thể tránh những vấn đề này bằng cách sử dụng Named Tuple. Tuple được đặt tên cho phép chúng tôi đặt tên cho các phần tử, vì vậy chúng tôi có thể truy cập các thuộc tính bằng cả tên thuộc tính và chỉ mục của nó
Thực tế, có hai loại Tuple được đặt tên trong Python3. 8. Một là từ gói collections
đã tồn tại từ lâu, một là từ gói typing
đã được giới thiệu từ Python3. 6
bộ sưu tập. têntuple
Tôi sẽ bắt đầu với gói collections
. Gói này cung cấp các lựa chọn thay thế cho các loại tích hợp chung của Python như dict, list, set và tuple
Đây là cách tạo một lớp namedtuple
. WOW, chỉ một dòng mã
Transaction
chúng ta vừa tạo thực chất là một lớp. Nó có các thuộc tính người gửi, người nhận, ngày, số tiền và _fields
, cho phép chúng tôi truy cập thuộc tính theo cả tên và chỉ mục
Tạo một đối tượng
Tạo một đối tượng được đặt tên cũng đơn giản như tạo lớp. Điều tôi cũng thích là đại diện của đối tượng được đặt tên. Bạn cũng có thể tùy chỉnh nó trong lớp Python thông thường của mình bằng cách ghi đè phương thức __repr__
Cũng có thể gán thuộc tính với giá trị mặc định
têntuple-tạo-mặc định. py⚠️ ️Chú ý
têntuple-tạo-mặc định-cẩn thận. pyTrong ví dụ này, tôi chỉ gán __init__
0 cho một thuộc tính làm giá trị mặc định. Thuộc tính nào được gán?
__init__
0 được gán cho thuộc tính __init__
2, là thuộc tính cuối cùng của bộ dữ liệu
Có chuyện gì ở đây vậy?
Ổn thỏa. Về cơ bản, việc tạo Named Tuple tuân theo cú pháp giống như lớp Python thông thường
Điều kỳ diệu là khi chúng ta tạo một lớp, đối số không mặc định không thể theo đối số mặc định. Trong lớp Python thông thường, chúng ta sẽ nhận thấy ngay lỗi này. Quy tắc cú pháp này cũng áp dụng trong Tuple được đặt tên, vì vậy giá trị mặc định sẽ được gán bắt đầu từ phần tử cuối cùng
têntuple-tạo-mặc định-lớp thông thường. pyQuay lại chủ đề phụ. tạo một đối tượng. Cũng có thể tạo đối tượng namedtuple
bằng phương thức __init__
4. Nhưng bạn cần nhớ thứ tự của các thuộc tính
Truy cập thuộc tính
Truy cập thuộc tính trong namedtuple
cũng rất đơn giản. Trên thực tế, nó là một bộ dữ liệu, chúng ta có thể truy cập thuộc tính giống như cách chúng ta thực hiện với bộ dữ liệu cơ bản. Một namedtuple
có thể được chuyển đổi thành một từ điển với __init__
7
Gán thuộc tính
Chờ đợi?
Điều đó phụ thuộc vào kiểu dữ liệu của các thuộc tính tuple. Nếu thuộc tính là bất biến như str, float, int, thì chúng ta không thể sửa đổi trạng thái, chẳng hạn như __init__
8
Nhưng nếu bản thân thuộc tính có thể thay đổi như danh sách, bạn được phép thay đổi các phần tử bên trong danh sách mà không cần để bộ nhận biết về sự thay đổi
têntuple với thuộc tính có thể thay đổi
Trong ví dụ này, người gửi là một danh sách là một đối tượng có thể thay đổi. Trước khi sửa thuộc tính, mình sử dụng hàm có sẵn trong Python là __init__
9 để kiểm tra địa chỉ bộ nhớ của danh sách
Sau đó, tôi thay đổi phần tử thứ hai của danh sách thành “gaga” và in ra id của cùng một danh sách. Hóa ra id giống nhau. Vì vậy, đối với namedtuple, trạng thái không bị thay đổi
têntuple với thuộc tính có thể thay đổi 2
Nhưng nếu chúng ta tạo một danh sách mới với các phần tử giống nhau. “jojo” và “gaga” và cố gắng gán nó cho bộ được đặt tên, nó sẽ không hoạt động vì chúng có các id khác nhau
lớp kế thừa
Đôi khi chúng ta muốn kế thừa một lớp và mở rộng các thuộc tính. Trong namedtuple
, bạn có thể thêm một thuộc tính mới bằng cách sử dụng {"sender":"","receiver":"","date":"","amount":""}
1. Nó chỉ đơn giản như những gì bạn nhìn thấy
Gán tên trường cho kết quả trong bộ được trả về bởi truy vấn csv hoặc db
Một tính năng thú vị khác mà tôi thích về namedtuple
là nó có thể ánh xạ bản ghi csv hoặc kết quả truy vấn db tới một đối tượng được đặt tên. Nó có thể giảm số lượng mã soạn sẵn
đánh máy. tênTuple
Tùy chọn thứ hai để tạo một bộ có tên là sử dụng {"sender":"","receiver":"","date":"","amount":""}
3. Nó đến từ gói typing
, vì vậy mọi thuộc tính được liên kết với một loại. Theo tôi, đó là điểm khác biệt duy nhất giữa {"sender":"","receiver":"","date":"","amount":""}
5 và {"sender":"","receiver":"","date":"","amount":""}
3
Định dạng trông hơi giống lớp Python thông thường nhưng với kiểu gõ. Hãy chắc chắn rằng bạn kế thừa {"sender":"","receiver":"","date":"","amount":""}
3
Lớp được tạo từ {"sender":"","receiver":"","date":"","amount":""}
3 có thêm trường {"sender":"","receiver":"","date":"","amount":""}
9 hiển thị loại được xác định của từng thuộc tính
Đôi khi, nếu bạn không thực sự muốn xác định một loại cho các thuộc tính nhất định, bạn có thể sử dụng loại collections
0. Trình kiểm tra loại tĩnh sẽ coi mọi loại đều tương thích với Any
Tạo một đối tượng, Truy cập thuộc tính và Gán thuộc tính
NamedTuple-truy cập. pyVề cách tạo đối tượng, truy cập thuộc tính và gán thuộc tính, {"sender":"","receiver":"","date":"","amount":""}
3 giống như collections
2
lớp dữ liệu
Dataclass là một tính năng mới được giới thiệu kể từ Python 3. 7. Nó được sử dụng như một trang trí. Những gì nó làm dưới mui xe là triển khai __init__
, __repr__
, v.v. cho chúng tôi
Tuple được đặt tên hoạt động giống như một bộ dữ liệu, trong khi lớp dữ liệu hoạt động giống như một lớp Python thông thường hơn. Tại sao tôi lại nói như vậy?
lớp kế thừa
Khi kế thừa một lớp dữ liệu, thuộc tính của lớp con sẽ theo sau lớp cha, vì vậy hãy cẩn thận với giá trị mặc định. Nếu một trường trong lớp cha được gán giá trị mặc định, thì tất cả các thuộc tính trong lớp con sẽ có giá trị mặc định
lớp dữ liệu kế thừa. pyLớp dữ liệu bất biến
Một trong những tính năng chính của Named Tuple là không thay đổi. Bạn cũng có thể đặt các thuộc tính không thay đổi trong lớp dữ liệu thông qua collections
5
Trong một lớp dữ liệu bị đóng băng, ngoại lệ collections
6 sẽ được nâng lên nếu bạn cố sửa đổi trạng thái
So sánh hiệu suất
Cuối cùng nhưng không kém phần quan trọng, tôi muốn so sánh hiệu suất của lớp Python thông thường, {"sender":"","receiver":"","date":"","amount":""}
5, {"sender":"","receiver":"","date":"","amount":""}
3 và collections
9. So sánh bao gồm
- kích thước của đối tượng
- thời gian để tạo đối tượng
- thời gian để lấy thuộc tính
Tôi đã tạo 5 lớp khác nhau. Cái cuối cùng là một lớp dữ liệu được tối ưu hóa với trường typing
0. Các vị trí được sử dụng để làm cho các lớp nhanh hơn và sử dụng ít bộ nhớ hơn
So sánh kích thước của đối tượng
Bước đầu tiên là so sánh kích thước của từng đối tượng được tạo bằng cách sử dụng typing
1
So sánh thời gian để tạo một đối tượng
Sau đó, tôi sử dụng hàm tích hợp Python typing
2 để so sánh thời gian tạo đối tượng
So sánh thời gian để truy cập một thuộc tính
têntuple-dataclass-truy cập-so sánh. pyKết quả
têntuple-dataclass-so sánh-kết quả. csvCác đối tượng dựa trên Tuple nói chung lớn hơn do thực tế là chúng chứa cả tên thuộc tính và chỉ mục. lớp dữ liệu với các vị trí có thời gian tạo đối tượng ít nhất. Lớp Python thông thường có vẻ tốt trong việc truy cập các thuộc tính