Tôi thường sử dụng ipython
trên dòng lệnh để tạo các ví dụ tối thiểu về những thứ tôi muốn thử. Khi tôi cần tạo những thứ liên quan đến một lớp, tôi thường thấy mình tạo một lớp, sử dụng nó một thời gian, sau đó khi tôi cần thêm các phương thức khác vào lớp hoặc chỉnh sửa một dòng, tôi phải nhấn mũi tên lên cho đến khi tôi
Vì vậy, tôi tự nghĩ, làm thế nào tôi có thể làm cho đoạn mã sau hoạt động?
class A:
pass
a = A[]def foo[]:
print['hello world!']### PYTHON MAGIC GOES HERE ###a.foo[] # hello world!
Sau khi xem qua các bài đăng tràn ngăn xếp như https. // stackoverflow. com/questions/17929543/how-can-i-dynamically-create-class-methods-for-a-class-in-python, tôi tình cờ phát hiện ra lệnh dựng sẵnsetattr
[] để hoàn thành nhiệm vụ
class A:
pass
a = A[]def foo[self]: # Have to add self since this will become a method
print['hello world!']setattr[A, 'foo', foo]a.foo[] # hello world!
Thật vậy, những điều trên không hoạt động. Tuy nhiên, tôi thấy giải pháp này khá không phù hợp
Trường hợp sử dụng này yêu cầu một số đoạn mã có thể tái sử dụng, để tôi có thể thêm bất kỳ chức năng nào vào bất kỳ lớp hiện có nào. Điều tôi muốn là trang trí bất kỳ chức năng nào để nó trở thành một phương thức cho lớp. Tôi muốn đoạn mã sau hoạt động
class A:
pass
a = A[]@add_method[A]
def foo[]:
print['hello world!']a.foo[] # hello world!
Tôi muốn gánh nặng công việc được thực hiện bởi người trang trí và không buộc lập trình viên phải thêm self
vào các hàm [điều này sẽ khiến các hàm không sử dụng được cho đến khi được liên kết với một lớp] và tôi muốn đơn giản hóa việc sử dụng setattr
luôn luôn
Sau khi làm theo dòng suy nghĩ này xuống hố thỏ trong khoảng một giờ, đây là kết quả
Bạn có thể sao chép dán cái này vào một tệp và tự mình dùng thử
Người trang trí
class A:0 làm tất cả những công việc nặng nhọc. Cả hai hàm
pass
a = A[]def foo[self]: # Have to add self since this will become a method
print['hello world!']setattr[A, 'foo', foo]a.foo[] # hello world!
foo
và class A:2 vẫn là các hàm hợp lệ sau khi chúng được ràng buộc dưới dạng phương thức
pass
a = A[]def foo[self]: # Have to add self since this will become a method
print['hello world!']setattr[A, 'foo', foo]a.foo[] # hello world!
Tôi không chắc điều này sẽ hữu ích đến mức nào [có thể không hữu ích chút nào]. Đây chỉ là loại điều mà tôi muốn thử nghiệm với ipython
Tìm hiểu cách sửa đổi phương thức __add__ của lớp Python để có thể thêm hai phiên bản của một đối tượng tùy chỉnh. Chúng tôi cũng nói về phương thức __radd__, cần thiết để tổng hợp danh sách các trường hợp.
Khi chúng ta tính tổng hai đối tượng trong Python, như
a + b
điều thực sự xảy ra là phương thức __add__ của a object is called:
a. __add__[b]
Điều đó có nghĩa là chúng ta có thể kiểm soát kết quả của tổng hai đối tượng bằng cách sửa đổi hoặc bỏ qua __add__ method.
Ví dụ: hãy tưởng tượng rằng chúng ta xác định một lớp Ngày , lớp này chứa các lượt truy cập và liên hệ mà một trang web tạo ra trong một ngày.
ngày học[đối tượng].
def __init__[bản thân, lượt truy cập, địa chỉ liên hệ].
bản thân. lượt truy cập = lượt truy cập
bản thân. địa chỉ liên hệ = địa chỉ liên hệ
def __str__[self].
quay lại “Lượt truy cập. %i, Địa chỉ liên hệ. %i” % [tự. thăm, bản thân. địa chỉ liên hệ]
và chúng tôi tạo hai phiên bản của đối tượng này
ngày 1 = Ngày[10, 1]
day2 = Day[20, 2]
để có thể
>>> print day1
Lượt truy cập. 10, Danh bạ. 1
>>> print day2
Lượt truy cập. 20, Danh bạ. 2
Chúng ta có thể xác định phương thức __add__ để trả về Ngày instance with the total number of visits and contacts:
ngày học[đối tượng].
…
def __add__[self, other].
total_visits = self. lượt truy cập + khác. lượt truy cập
total_contacts = self. danh bạ + khác. địa chỉ liên hệ
Ngày trả về[total_visits, total_contacts]
…
và bây giờ chúng ta chỉ có thể tính tổng hai trường hợp day1 và day2
>>> day3 = day1 + day2
>>> print day3
Lượt truy cập. 30, Danh bạ. 3
Tuy nhiên, nếu chúng ta cố gắng
day4 = sum[[day1, day2, day3]]
bạn sẽ nhận được một lỗi như
LoạiLỗi. [các] loại toán hạng không được hỗ trợ cho +. 'int' và 'Ngày'
Điều này là do phương thức tính tổng bắt đầu bằng số nguyên 0 và phương thức này sẽ thử.
0. __thêm__[ngày1]
Tuy nhiên, phương thức __add__ của một số nguyên không biết gì về cách tính tổng . Do đó, nó cố gắng gọi phương thức thêm ngược lại. instance. Therefore, it tries to call the reverse add method:
1 ngày. __radd__[0]
mà chưa được xác định. Vì vậy, hãy làm điều đó. 😉
ngày học[đối tượng].
…
def __radd__[self, other].
nếu khác == 0.
tự trả lại
khác.
tự quay lại. __add__[khác]
…
vì vậy bây giờ, chúng ta có thể sử dụng sum để thêm Ngày instances!
Mã đầy đủ là
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Tệp. marinamele_add_method. py
-----------------------------
lớp Ngày[đối tượng]:
def __init__[self, visits, contacts]:
bản thân. lượt truy cập = lượt truy cập
bản thân. liên hệ = liên hệ
def __add__[self, other]:
total_visits = self. lượt truy cập + khác. lượt truy cập
total_contacts = self. liên hệ + khác. địa chỉ liên hệ
lượt về Ngày[total_visits, total_contacts]
def __radd__[self, other]:
nếu khác == 0:
trả về chính mình
khác.
trả về chính mình. __add__[khác]
def __str__[self]:
return "Visits: %i, Danh bạ. %i" . % [self.lượt truy cập, bản thân. địa chỉ liên hệ]
day1 = Day[10, 1]
day2 = Ngày[20, 2]
in ngày 1day1
# lượt truy cập. 10, Danh bạ. 1
in ngày 2
# lượt truy cập. 20, Danh bạ. 2
day3 = day1 + day2
in ngày 3
# lượt truy cập. 30, Danh bạ. 3
day4 = sum[[day1, day2, day3]]
in ngày 4
# lượt truy cập. 60, Danh bạ. 6
Mẹo Django . Bạn cũng có thể xác định phương thức __add__ trong các mô hình Django của mình.
Hy vọng nó hữu ích
Bài đăng mới. Sửa đổi phương thức __add__ của Lớp Python để kiểm soát tổng của hai đối tượng tùy chỉnh http. //t. co/3IZIn9wG2z
— Marina Mele [@Marina_Mele] ngày 16 tháng 4 năm 2014