2009-05-04 19 views
5

Tôi đọc hướng dẫn Bão ORM tại https://storm.canonical.com/Tutorial, và tôi stumbled khi các đoạn mã sau:tính năng python nào được minh họa trong mã này?


store.find(Person, Person.name == u"Mary Margaret").set(name=u"Mary Maggie") 

Tôi không chắc chắn rằng đối số thứ hai của tìm phương pháp sẽ được đánh giá để True/False. Tôi nghĩ nó sẽ được hiểu là một lambda. Nếu đó là sự thật, làm thế nào tôi có thể đạt được hiệu quả tương tự trong các chức năng của tôi?

Trả lời

0

vì tôi là một lập trình viên Java ... Tôi đoán ... đó là quá tải toán tử? Person.name == là một nhà điều hành quá tải mà thay vào đó làm so sánh ... nó tạo ra một truy vấn SQL

tôi 0.02 $

+0

Quá tải Java và toán tử ... không nghĩ nó sẽ trở thành hiện thực. Ở phía bên kia, có thể bạn đã đúng. – Geo

+10

Odd .... Chấp nhận câu trả lời "đoán" khi câu trả lời khác dựa trên mã nguồn thực tế trong Storm. –

+0

xin lỗi, nhưng tôi đoán là "đủ nhanh" :-) PS bạn nói đúng, rất kỳ quặc! – dfa

1

Nó không giống như một lambda python với tôi. Tôi đã không đọc mã cho Storm nhưng Miles có lẽ là đúng ở chỗ nó sử dụng một lược đồ đánh giá lười biếng.

Để tìm hiểu thêm về hàm lambda python, hãy đọc số chapter tuyệt vời của Dive Into Python.

+0

Tôi luôn nghĩ rằng các hàm lambda phải được bắt đầu bằng từ khóa lambda, vì vậy đây không phải là trường hợp, đúng không? – Geo

22

Person.name có phương thức quá tải __eq__ không trả về giá trị boolean mà là đối tượng lưu trữ cả hai mặt của biểu thức; đối tượng đó có thể được kiểm tra bằng phương thức find() để lấy thuộc tính và giá trị mà nó sẽ sử dụng để lọc. Tôi sẽ mô tả điều này như một loại mô hình đánh giá lười biếng.

Trong cơn bão, nó được triển khai với Comparable object.

8

Phép thuật nằm trong thuộc tính Person.name, dẫn đến một loại quá tải __eq__ (& c) để trả về không có bool. Các nguồn của Storm trực tuyến để bạn có thể duyệt (và bắt chước ;-) tại số http://bazaar.launchpad.net/~storm/storm/trunk/files/head%3A/storm/ - như bạn sẽ thấy, chúng không sáng trên "ma thuật đen" ;-)

9

Person.name là một thể hiện của một số nhập với phương thức tùy chỉnh __eq__. Trong khi __eq__ thường trả về một giá trị boolean (ish), nó thực sự có thể trả lại bất cứ điều gì bạn muốn, bao gồm một lambda. Xem Python special method names để biết thêm về điều này và các phương pháp liên quan.

Có lẽ khó hiểu nhất/gây hiểu lầm là một phần của việc này (đặc biệt là nếu bạn đang sử dụng các ngôn ngữ OO khác như Java) là Person.nameperson.name (nơi person là một thể hiện của Person) không cần phải có bất kỳ mối quan hệ với lẫn nhau. Ví dụ:

class Person(object): 
    name = "name of class" 
    def __init__(self): 
    self.name = "name of instance" 

person = Person() 
print Person.name 
print person.name 

này sẽ in:

name of class 
name of instance 

Lưu ý rằng thuộc tính lớp chỉ được thiết lập trong cơ thể lớp, trong khi tài sản chẳng hạn được thiết lập trong phương pháp __init__.

Trong trường hợp của bạn, bạn nên đặt Person.name đến đối tượng với tùy chỉnh __eq__ phương thức trả về một lambda, một cái gì đó như thế này:

class LambdaThingy(object): 
    def __init__(self, attrname): 
    self.__attrname = attrname 

    def __eq__(self, other): 
    return lambda x: getattr(x, self.__attrname) == other 

class Person(object): 
    name = LambdaThingy('name') 

    def __init__(self, name): 
    self.name = name 

equals_fred = Person.name == "Fred" 
equals_barney = Person.name == "Barney" 

fred = Person("Fred") 

print equals_fred(fred) 
print equals_barney(fred) 

in này:

True 
False 

Điều này chắc chắn là ốp cạnh của "quá thông minh", vì vậy tôi sẽ rất thận trọng về việc sử dụng điều này trong mã sản xuất. Một lambda rõ ràng có lẽ sẽ rõ ràng hơn rất nhiều đối với các nhà bảo trì trong tương lai, ngay cả khi nó có một chút chi tiết hơn.

+0

+1 cho giải thích tuyệt vời về phần "quá thông minh"! – lothar

Các vấn đề liên quan