ฉันกำลังดูโค้ด Python บางตัวที่ใช้@
สัญลักษณ์ แต่ฉันไม่รู้ว่ามันทำอะไร ฉันไม่ทราบด้วยว่าจะค้นหาสิ่งใดในการค้นหา Python docs หรือ Google จะไม่แสดงผลลัพธ์ที่เกี่ยวข้องเมื่อ@
มีการรวมสัญลักษณ์
ฉันกำลังดูโค้ด Python บางตัวที่ใช้@
สัญลักษณ์ แต่ฉันไม่รู้ว่ามันทำอะไร ฉันไม่ทราบด้วยว่าจะค้นหาสิ่งใดในการค้นหา Python docs หรือ Google จะไม่แสดงผลลัพธ์ที่เกี่ยวข้องเมื่อ@
มีการรวมสัญลักษณ์
คำตอบ:
@
สัญลักษณ์ที่จุดเริ่มต้นของเส้นที่ใช้สำหรับการเรียนการทำงานและวิธีการตกแต่ง
อ่านเพิ่มเติมได้ที่นี่:
เครื่องมือตกแต่ง Python ที่คุณใช้บ่อยที่สุดคือ:
ถ้าคุณเห็น@
เส้นกึ่งกลางของเส้นนั่นก็คือการคูณเมทริกซ์ที่แตกต่างกัน เลื่อนลงไปดูคำตอบอื่น ๆ @
ที่อยู่ที่การใช้งานของ
class Pizza(object):
def __init__(self):
self.toppings = []
def __call__(self, topping):
# When using '@instance_of_pizza' before a function definition
# the function gets passed onto 'topping'.
self.toppings.append(topping())
def __repr__(self):
return str(self.toppings)
pizza = Pizza()
@pizza
def cheese():
return 'cheese'
@pizza
def sauce():
return 'sauce'
print pizza
# ['cheese', 'sauce']
นี่แสดงให้เห็นว่าfunction
/ method
/ class
คุณกำลังกำหนดหลังจากมัณฑนากรเพียงแค่ส่งต่อargument
ไปยังfunction
/ ถึงmethod
ทันทีหลังจากที่@
ลงชื่อเข้าใช้
การออกแบบ microframework Flaskเริ่มจากนักตกแต่งในรูปแบบต่อไปนี้
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
สิ่งนี้จะแปลเป็น:
rule = "/"
view_func = hello
# They go as arguments here in 'flask/app.py'
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
pass
การตระหนักถึงสิ่งนี้ในที่สุดก็ทำให้ฉันรู้สึกสงบสุขกับ Flask
app.route("/")
: ฟังก์ชั่นนี้จะส่งคืนฟังก์ชันซึ่งคุณเรียกใช้ด้วยhello()
อาร์กิวเมนต์ของคุณ
app.route("/", hello)
ทันทีหลังจากกำหนดhello
หรือแม้แต่กำหนดhello
เป็นแลมบ์ดาในการโต้แย้งapp.route
? (ตัวอย่างหลังเป็นเรื่องธรรมดากับhttp.Server
เส้นทางNode.js และเส้นทางด่วน)
ข้อมูลโค้ดนี้:
def decorator(func):
return func
@decorator
def some_func():
pass
เทียบเท่ากับรหัสนี้:
def decorator(func):
return func
def some_func():
pass
some_func = decorator(some_func)
ในคำจำกัดความของมัณฑนากรคุณสามารถเพิ่มบางสิ่งที่ปรับเปลี่ยนซึ่งจะไม่ถูกส่งกลับโดยฟังก์ชัน
ใน Python 3.5 คุณสามารถโอเวอร์โหลด@
ในฐานะผู้ดำเนินการ มันถูกตั้งชื่อเป็น__matmul__
เพราะมันถูกออกแบบมาเพื่อทำการคูณเมทริกซ์ แต่มันสามารถเป็นอะไรก็ได้ที่คุณต้องการ ดูรายละเอียดPEP465
นี่เป็นการใช้งานการคูณเมทริกซ์อย่างง่าย
class Mat(list):
def __matmul__(self, B):
A = self
return Mat([[sum(A[i][k]*B[k][j] for k in range(len(B)))
for j in range(len(B[0])) ] for i in range(len(A))])
A = Mat([[1,3],[7,5]])
B = Mat([[6,8],[4,2]])
print(A @ B)
รหัสนี้ให้ผล:
[[18, 14], [62, 66]]
@=
(ในสถานที่) __imatmul__
ผู้ประกอบการซึ่งเป็น
__add__
และ__sub__
เชื่อมโยงกับ + และ - ตามลำดับ แต่ไม่เคยได้ยิน@
เครื่องหมายใดมาก่อน มีคนอื่นบ้างไหมที่ซุ่มซ่อนอยู่ที่นั่น?
กล่าวโดยย่อคือมันใช้ในไวยากรณ์มัณฑนากรและการคูณเมทริกซ์
ในบริบทของการตกแต่งไวยากรณ์นี้:
@decorator
def decorated_function():
"""this function is decorated"""
เทียบเท่ากับสิ่งนี้:
def decorated_function():
"""this function is decorated"""
decorated_function = decorator(decorated_function)
ในบริบทของการคูณเมทริกซ์a @ b
เรียกใช้a.__matmul__(b)
- สร้างไวยากรณ์นี้:
a @ b
เทียบเท่ากับ
dot(a, b)
และ
a @= b
เทียบเท่ากับ
a = dot(a, b)
โดยที่dot
ตัวอย่างฟังก์ชันการคูณเมทริกซ์ numpy และa
และb
เป็นเมทริกซ์
ฉันไม่ทราบด้วยว่าจะค้นหาสิ่งใดในการค้นหา Python docs หรือ Google จะไม่แสดงผลลัพธ์ที่เกี่ยวข้องเมื่อมีสัญลักษณ์ @ รวมอยู่ด้วย
หากคุณต้องการมีมุมมองที่ค่อนข้างสมบูรณ์เกี่ยวกับสิ่งที่ไวยากรณ์ของส่วนใดของ python ให้ดูที่ไฟล์ไวยากรณ์โดยตรง สำหรับสาขา Python 3:
~$ grep -C 1 "@" cpython/Grammar/Grammar
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
--
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
'<<=' | '>>=' | '**=' | '//=')
--
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power
เราสามารถดูที่นี่ที่@
ใช้ในสามบริบท:
การค้นหา google สำหรับ "decorator python docs" เป็นหนึ่งในผลลัพธ์อันดับต้น ๆ ส่วน "คำสั่งผสม" ของ "Python Language Reference" เลื่อนลงไปยังส่วนที่เกี่ยวกับคำจำกัดความของฟังก์ชั่นซึ่งเราสามารถค้นหาได้โดยการค้นหาคำว่า "มัณฑนากร" เราจะเห็นว่า ... มีอะไรให้อ่านมากมาย แต่คำว่า"มัณฑนากร" เป็นลิงค์ไปยังอภิธานศัพท์ซึ่งบอกเราว่า:
มัณฑนากร
ฟังก์ชั่นกลับมาฟังก์ชั่นอื่นมักจะใช้เป็นการแปลงฟังก์ชั่นโดยใช้
@wrapper
ไวยากรณ์ ตัวอย่างทั่วไปสำหรับตกแต่งเป็นและclassmethod()
staticmethod()
ไวยากรณ์มัณฑนากรเป็นเพียงน้ำตาลเชิงประโยคเพียงสองคำจำกัดความฟังก์ชันต่อไปนี้เทียบเท่ากับ semantically:
def f(...): ... f = staticmethod(f) @staticmethod def f(...): ...
มีแนวคิดเดียวกันสำหรับคลาส แต่มีการใช้งานน้อยกว่าปกติ ดูเอกสารประกอบสำหรับคำนิยามฟังก์ชั่นและคำจำกัดความของชั้นเรียนสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการตกแต่ง
ดังนั้นเราจะเห็นว่า
@foo
def bar():
pass
มีความหมายเหมือนกับ:
def bar():
pass
bar = foo(bar)
พวกเขาจะไม่เหมือนกันเพราะ Python ประเมินการแสดงออก foo (ซึ่งอาจเป็นการค้นหาประและฟังก์ชั่นการโทร) ก่อนที่แถบด้วย@
ไวยากรณ์มัณฑนากร ( ) แต่ประเมินการแสดงออกของ foo หลังจากบาร์ในกรณีอื่น ๆ
(หากความแตกต่างนี้สร้างความแตกต่างในความหมายของรหัสของคุณคุณควรพิจารณาสิ่งที่คุณทำกับชีวิตของคุณเพราะมันจะเป็นพยาธิวิทยา)
ถ้าเรากลับไปที่เอกสารไวยากรณ์ของนิยามฟังก์ชันเราจะเห็น:
@f1(arg) @f2 def func(): pass
เทียบเท่ากับ
def func(): pass func = f1(arg)(f2(func))
นี่คือการสาธิตที่เราสามารถเรียกใช้ฟังก์ชันที่เป็นมัณฑนากรก่อนเช่นเดียวกับผู้ตกแต่งสแต็ค ฟังก์ชั่นใน Python เป็นวัตถุชั้นหนึ่ง - ซึ่งหมายความว่าคุณสามารถส่งผ่านฟังก์ชั่นเป็นข้อโต้แย้งไปยังฟังก์ชั่นอื่นและกลับมาฟังก์ชั่น ผู้ตกแต่งทำสิ่งเหล่านี้ทั้งสอง
ถ้าเราสแต็คตกแต่งภายในฟังก์ชันตามที่กำหนดไว้จะถูกส่งผ่านไปยังมัณฑนากรก่อนจากนั้นต่อไปเรื่อย ๆ
นั่นคือผลรวมการใช้@
ในบริบทของนักตกแต่ง
@
ในส่วนการวิเคราะห์คำศัพท์ของการอ้างอิงภาษาเรามีส่วนที่เกี่ยวกับตัวดำเนินการซึ่งรวมถึง@
ซึ่งทำให้มันเป็นตัวดำเนินการด้วย:
โทเค็นต่อไปนี้เป็นโอเปอเรเตอร์:
+ - * ** / // % @ << >> & | ^ ~ < > <= >= == !=
และในหน้าถัดไปรูปแบบข้อมูลที่เรามีส่วนประเภทการลอกเลียนแบบตัวเลข ,
object.__add__(self, other) object.__sub__(self, other) object.__mul__(self, other) object.__matmul__(self, other) object.__truediv__(self, other) object.__floordiv__(self, other)
[... ] วิธีการเหล่านี้ถูกเรียกให้ใช้การดำเนินการทางเลขฐานสอง (
+
,-
,*
,@
,/
,//
[ ... ]
และเราเห็นว่า __matmul__
@
สอดคล้องกับ หากเราค้นหาเอกสารสำหรับ "matmul" เราจะได้รับลิงค์ไปยังมีอะไรใหม่ใน Python 3.5ด้วย "matmul" ภายใต้หัวข้อ "PEP 465 - ตัวดำเนินการมัดเฉพาะสำหรับการคูณเมทริกซ์"
จะสามารถดำเนินการโดยการกำหนด
__matmul__()
,__rmatmul__()
และ__imatmul__()
ปกติสะท้อนให้เห็นและในสถานที่คูณเมทริกซ์
(ตอนนี้เราเรียนรู้ว่า@=
เป็นรุ่นในสถานที่) มันอธิบายเพิ่มเติม:
การคูณเมทริกซ์เป็นการดำเนินการที่พบได้ทั่วไปในหลายสาขาของคณิตศาสตร์วิทยาศาสตร์วิศวกรรมและการเพิ่ม @ อนุญาตให้เขียนโค้ดที่สะอาดกว่า:
S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)
แทน:
S = dot((dot(H, beta) - r).T, dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))
ในขณะที่โอเปอเรเตอร์สามารถโอเวอร์โหลดเพื่อทำเกือบทุกอย่างในnumpy
ตัวอย่างเช่นเราจะใช้ไวยากรณ์นี้เพื่อคำนวณผลิตภัณฑ์ภายในและภายนอกของอาร์เรย์และเมทริกซ์:
>>> from numpy import array, matrix
>>> array([[1,2,3]]).T @ array([[1,2,3]])
array([[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
>>> array([[1,2,3]]) @ array([[1,2,3]]).T
array([[14]])
>>> matrix([1,2,3]).T @ matrix([1,2,3])
matrix([[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
>>> matrix([1,2,3]) @ matrix([1,2,3]).T
matrix([[14]])
@=
ขณะทำการค้นคว้าการใช้งานก่อนหน้านี้เราได้เรียนรู้ว่ายังมีการคูณเมทริกซ์แบบ inplace หากเราพยายามใช้งานเราอาจพบว่ายังไม่ได้ใช้งานสำหรับผู้ใช้จำนวนมาก:
>>> m = matrix([1,2,3])
>>> m @= m.T
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: In-place matrix multiplication is not (yet) supported. Use 'a = a @ b' instead of 'a @= b'.
เมื่อมีการใช้งานฉันคาดว่าผลลัพธ์จะเป็นดังนี้:
>>> m = matrix([1,2,3])
>>> m @= m.T
>>> m
matrix([[14]])
สัญลักษณ์“ at” (@) ทำอะไรใน Python
สัญลักษณ์ @ เป็นงูหลาม syntactic น้ำตาลให้ใช้decorator
ใน
การถอดความคำถามมันเกี่ยวกับสิ่งที่ช่างตกแต่งทำในงูหลามอะไร?
ใส่ง่ายdecorator
ช่วยให้คุณสามารถแก้ไขคำจำกัดความของฟังก์ชั่นที่กำหนดได้โดยไม่ต้องสัมผัสส่วนในสุด (ปิด)
เป็นกรณีส่วนใหญ่เมื่อคุณนำเข้าแพ็คเกจที่ยอดเยี่ยมจากบุคคลที่สาม คุณสามารถมองเห็นมันคุณสามารถใช้งานได้ แต่คุณไม่สามารถสัมผัสภายในและหัวใจของมัน
นี่คือตัวอย่างด่วน
สมมติว่าฉันกำหนดread_a_book
ฟังก์ชันบน Ipython
In [9]: def read_a_book():
...: return "I am reading the book: "
...:
In [10]: read_a_book()
Out[10]: 'I am reading the book: '
คุณเห็นฉันลืมที่จะเพิ่มชื่อมัน
วิธีแก้ปัญหาดังกล่าว? แน่นอนฉันสามารถกำหนดฟังก์ชั่นใหม่เป็น:
def read_a_book():
return "I am reading the book: 'Python Cookbook'"
อย่างไรก็ตามจะเกิดอะไรขึ้นถ้าฉันไม่ได้รับอนุญาตให้จัดการฟังก์ชั่นดั้งเดิมหรือหากมีฟังก์ชั่นดังกล่าวนับพันที่ต้องจัดการ
แก้ไขปัญหาด้วยการคิดต่าง ๆ และกำหนด new_function
def add_a_book(func):
def wrapper():
return func() + "Python Cookbook"
return wrapper
จากนั้นจ้างมัน
In [14]: read_a_book = add_a_book(read_a_book)
In [15]: read_a_book()
Out[15]: 'I am reading the book: Python Cookbook'
คุณเห็นไหมว่า Tada ฉันแก้ไขread_a_book
โดยไม่แตะต้องมัน decorator
ไม่มีอะไรหยุดฉันพร้อมกับ
เกี่ยวกับอะไร @
@add_a_book
def read_a_book():
return "I am reading the book: "
In [17]: read_a_book()
Out[17]: 'I am reading the book: Python Cookbook'
@add_a_book
เป็นวิธีแฟนซีและสะดวกในการพูดread_a_book = add_a_book(read_a_book)
มันเป็นน้ำตาล syntactic ไม่มีอะไรที่นักเล่นเพิ่มเติมเกี่ยวกับมัน
ถ้าคุณจะหมายถึงรหัสบางอย่างในโน๊ตบุ๊คหลามซึ่งมีการใช้Numpyห้องสมุดแล้ว@ operator
หมายถึงการคูณเมทริกซ์ ตัวอย่างเช่น:
import numpy as np
def forward(xi, W1, b1, W2, b2):
z1 = W1 @ xi + b1
a1 = sigma(z1)
z2 = W2 @ a1 + b2
return z2, a1
เริ่มต้นด้วย Python 3.5, '@' ถูกใช้เป็นสัญลักษณ์ infix เฉพาะสำหรับ MATRIX MULTIPLICATION (PEP 0465 - ดูhttps://www.python.org/dev/peps/pep-0465/ )
มีการเพิ่มผู้ตกแต่งใน Python เพื่อให้การทำงานและวิธีการห่อ (ฟังก์ชั่นที่ได้รับฟังก์ชั่นและส่งกลับหนึ่งปรับปรุง) ง่ายต่อการอ่านและเข้าใจ กรณีการใช้งานดั้งเดิมจะสามารถกำหนดวิธีการเป็นวิธีการเรียนหรือวิธีการคงที่บนหัวของคำนิยามของพวกเขา หากไม่มีไวยากรณ์มัณฑนากรมันจะต้องมีคำจำกัดความค่อนข้างเบาบางและซ้ำ ๆ :
class WithoutDecorators:
def some_static_method():
print("this is static method")
some_static_method = staticmethod(some_static_method)
def some_class_method(cls):
print("this is class method")
some_class_method = classmethod(some_class_method)
หากมีการใช้ไวยากรณ์ของมัณฑนากรเพื่อจุดประสงค์เดียวกันรหัสจะสั้นและง่ายต่อการเข้าใจ:
class WithDecorators:
@staticmethod
def some_static_method():
print("this is static method")
@classmethod
def some_class_method(cls):
print("this is class method")
ไวยากรณ์ทั่วไปและการใช้งานที่เป็นไปได้
มัณฑนากรโดยทั่วไปเป็นวัตถุที่มีชื่อ ( ไม่อนุญาตให้ใช้นิพจน์แลมบ์ดา ) ที่รับอาร์กิวเมนต์เดี่ยวเมื่อถูกเรียก (มันจะเป็นฟังก์ชั่นการตกแต่ง) และส่งกลับวัตถุที่เรียกได้อีกอันหนึ่ง "Callable" ใช้ที่นี่แทน "function" พร้อมการไตร่ตรองล่วงหน้า ในขณะที่นักตกแต่งมักจะกล่าวถึงในขอบเขตของวิธีการและฟังก์ชั่นพวกเขาจะไม่ จำกัด เพียงพวกเขา ในความเป็นจริงสิ่งใดที่เรียกได้ (วัตถุใด ๆ ที่ใช้วิธี _call__ นั้นถือว่าเรียกได้ว่า) สามารถใช้เป็นมัณฑนากรและบ่อยครั้งที่วัตถุที่ส่งคืนโดยพวกเขาไม่ใช่ฟังก์ชั่นที่ง่าย แต่อินสแตนซ์เพิ่มเติม
ไวยากรณ์มัณฑนากรเป็นเพียงเฉพาะน้ำตาลประโยค พิจารณาการใช้มัณฑนากรต่อไปนี้:
@some_decorator
def decorated_function():
pass
สิ่งนี้สามารถถูกแทนที่ด้วยการเรียกมัณฑนากรอย่างชัดเจนและการกำหนดฟังก์ชันใหม่:
def decorated_function():
pass
decorated_function = some_decorator(decorated_function)
อย่างไรก็ตามหลังสามารถอ่านได้น้อยและยากที่จะเข้าใจหากมีการใช้เครื่องมือตกแต่งหลายอย่างในฟังก์ชั่นเดียว มัณฑนากรสามารถใช้งานได้หลายวิธีดังแสดงด้านล่าง:
เป็นฟังก์ชั่น
มีหลายวิธีในการเขียนผู้ตกแต่งที่กำหนดเอง แต่วิธีที่ง่ายที่สุดคือการเขียนฟังก์ชั่นที่คืนค่าฟังก์ชันย่อยที่ตัดการเรียกใช้ฟังก์ชันดั้งเดิม
รูปแบบทั่วไปมีดังนี้:
def mydecorator(function):
def wrapped(*args, **kwargs):
# do some stuff before the original
# function gets called
result = function(*args, **kwargs)
# do some stuff after function call and
# return the result
return result
# return wrapper as a decorated function
return wrapped
เป็นคลาส
ในขณะที่มัณฑนากรเกือบทุกคนสามารถนำมาใช้โดยใช้ฟังก์ชั่นมีบางสถานการณ์เมื่อใช้คลาสที่ผู้ใช้กำหนดเองเป็นตัวเลือกที่ดีกว่า เรื่องนี้มักจะเกิดขึ้นจริงเมื่อมัณฑนากรต้องการ parametrization ที่ซับซ้อนหรือขึ้นอยู่กับสถานะที่เฉพาะเจาะจง
รูปแบบทั่วไปสำหรับมัณฑนากร nonparametrized เป็นคลาสมีดังต่อไปนี้:
class DecoratorAsClass:
def __init__(self, function):
self.function = function
def __call__(self, *args, **kwargs):
# do some stuff before the original
# function gets called
result = self.function(*args, **kwargs)
# do some stuff after function call and
# return the result
return result
นักออกแบบตกแต่งภายใน
ในรหัสจริงมักจะมีความต้องการที่จะใช้การตกแต่งที่สามารถ parametrized เมื่อใช้ฟังก์ชั่นเป็นมัณฑนากรแล้ววิธีการแก้ก็ง่าย - ต้องใช้การห่อในระดับที่สอง นี่คือตัวอย่างง่ายๆของมัณฑนากรที่ทำหน้าที่เรียกใช้ฟังก์ชั่นการตกแต่งซ้ำตามจำนวนครั้งที่ระบุทุกครั้งที่เรียกใช้:
def repeat(number=3):
"""Cause decorated function to be repeated a number of times.
Last value of original function call is returned as a result
:param number: number of repetitions, 3 if not specified
"""
def actual_decorator(function):
def wrapper(*args, **kwargs):
result = None
for _ in range(number):
result = function(*args, **kwargs)
return result
return wrapper
return actual_decorator
มัณฑนากรที่กำหนดด้วยวิธีนี้สามารถยอมรับพารามิเตอร์:
>>> @repeat(2)
... def foo():
... print("foo")
...
>>> foo()
foo
foo
โปรดทราบว่าแม้ว่ามัณฑนากร parametrized มีค่าเริ่มต้นสำหรับอาร์กิวเมนต์อาร์กิวเมนต์จะต้องอยู่ในวงเล็บหลังชื่อ วิธีที่ถูกต้องในการใช้มัณฑนากรก่อนหน้านี้ที่มีอาร์กิวเมนต์เริ่มต้นมีดังนี้:
>>> @repeat()
... def bar():
... print("bar")
...
>>> bar()
bar
bar
bar
ในที่สุดให้ดูการตกแต่งด้วยคุณสมบัติ
คุณสมบัติ
คุณสมบัติจัดเตรียมชนิดdescriptorในตัวที่รู้วิธีเชื่อมโยงแอ็ตทริบิวต์กับชุดของเมธอด พร็อพเพอร์ตี้มีอาร์กิวเมนต์ที่เป็นทางเลือกสี่แบบ: fget, fset, fdel และ doc คนสุดท้ายที่สามารถให้เพื่อกำหนด docstring ที่เชื่อมโยงกับคุณลักษณะราวกับว่ามันเป็นวิธีการ นี่คือตัวอย่างของคลาสสี่เหลี่ยมผืนผ้าที่สามารถควบคุมได้โดยการเข้าถึงคุณสมบัติที่เก็บจุดสองมุมโดยตรงหรือโดยใช้คุณสมบัติความกว้างและความสูง:
class Rectangle:
def __init__(self, x1, y1, x2, y2):
self.x1, self.y1 = x1, y1
self.x2, self.y2 = x2, y2
def _width_get(self):
return self.x2 - self.x1
def _width_set(self, value):
self.x2 = self.x1 + value
def _height_get(self):
return self.y2 - self.y1
def _height_set(self, value):
self.y2 = self.y1 + value
width = property(
_width_get, _width_set,
doc="rectangle width measured from left"
)
height = property(
_height_get, _height_set,
doc="rectangle height measured from top"
)
def __repr__(self):
return "{}({}, {}, {}, {})".format(
self.__class__.__name__,
self.x1, self.y1, self.x2, self.y2
)
ไวยากรณ์ที่ดีที่สุดสำหรับการสร้างคุณสมบัติใช้คุณสมบัติเป็นมัณฑนากร สิ่งนี้จะลดจำนวนลายเซ็นของเมธอดภายในคลาสและทำให้โค้ดอ่านได้ง่ายขึ้นและบำรุงรักษาได้ ด้วยการตกแต่งระดับดังกล่าวจะกลายเป็น:
class Rectangle:
def __init__(self, x1, y1, x2, y2):
self.x1, self.y1 = x1, y1
self.x2, self.y2 = x2, y2
@property
def width(self):
"""rectangle height measured from top"""
return self.x2 - self.x1
@width.setter
def width(self, value):
self.x2 = self.x1 + value
@property
def height(self):
"""rectangle height measured from top"""
return self.y2 - self.y1
@height.setter
def height(self, value):
self.y2 = self.y1 + value
ที่จะพูดในสิ่งที่คนอื่นมีในวิธีที่แตกต่าง: ใช่มันเป็นมัณฑนากร
ใน Python มันเหมือนกับ:
สิ่งนี้สามารถใช้กับสิ่งที่มีประโยชน์ได้ทุกประเภททำไปได้เพราะฟังก์ชั่นเป็นวัตถุและเพียงแค่ต้องการคำแนะนำ
สัญลักษณ์ @ ยังใช้เพื่อการเข้าถึงตัวแปรภายใน plydata / หมีแพนด้า dataframe pandas.DataFrame.query
แบบสอบถาม ตัวอย่าง:
df = pandas.DataFrame({'foo': [1,2,15,17]})
y = 10
df >> query('foo > @y') # plydata
df.query('foo > @y') # pandas
มันบ่งบอกว่าคุณกำลังใช้มัณฑนากร นี่คือตัวอย่างของ Bruce Eckelจากปี 2008