คือf = 1..__truediv__
อะไร
f
เป็นวิธีพิเศษที่ถูกผูกไว้บนลอยที่มีค่าหนึ่ง โดยเฉพาะอย่างยิ่ง
1.0 / x
ใน Python 3 เรียกใช้:
(1.0).__truediv__(x)
หลักฐาน:
class Float(float):
def __truediv__(self, other):
print('__truediv__ called')
return super(Float, self).__truediv__(other)
และ:
>>> one = Float(1)
>>> one/2
__truediv__ called
0.5
ถ้าเราทำ:
f = one.__truediv__
เราเก็บชื่อที่ถูกผูกไว้กับวิธีที่ถูกผูกไว้
>>> f(2)
__truediv__ called
0.5
>>> f(3)
__truediv__ called
0.3333333333333333
หากเราทำการค้นหาจุดที่เป็นวงแคบนี้อาจประหยัดเวลาเล็กน้อย
การแยกแผนผังต้นไม้บทคัดย่อ (AST)
เราจะเห็นว่าการแยกวิเคราะห์ AST สำหรับนิพจน์บอกเราว่าเราได้รับ__truediv__
คุณลักษณะจากจำนวนจุดลอยตัว1.0
:
>>> import ast
>>> ast.dump(ast.parse('1..__truediv__').body[0])
"Expr(value=Attribute(value=Num(n=1.0), attr='__truediv__', ctx=Load()))"
คุณสามารถรับฟังก์ชั่นผลลัพธ์เดียวกันจาก:
f = float(1).__truediv__
หรือ
f = (1.0).__truediv__
การหัก
เราสามารถไปถึงที่นั่นได้โดยการหักเงิน
มาสร้างมันกันเถอะ
1 โดยตัวมันเองคือint
:
>>> 1
1
>>> type(1)
<type 'int'>
1 โดยมีระยะเวลาหลังจากเป็นทศนิยม:
>>> 1.
1.0
>>> type(1.)
<type 'float'>
จุดถัดไปโดยตัวมันเองจะเป็น SyntaxError แต่มันเริ่มต้นการค้นหาจุดบนอินสแตนซ์ของการลอย:
>>> 1..__truediv__
<method-wrapper '__truediv__' of float object at 0x0D1C7BF0>
ไม่มีใครพูดถึงเรื่องนี้ - นี่เป็น"วิธีการผูก"บนโฟลว์1.0
:
>>> f = 1..__truediv__
>>> f
<method-wrapper '__truediv__' of float object at 0x127F3CD8>
>>> f(2)
0.5
>>> f(3)
0.33333333333333331
เราสามารถทำฟังก์ชันเดียวกันให้อ่านได้มากขึ้น:
>>> def divide_one_by(x):
... return 1.0/x
...
>>> divide_one_by(2)
0.5
>>> divide_one_by(3)
0.33333333333333331
ประสิทธิภาพ
ข้อเสียของdivide_one_by
ฟังก์ชั่นคือต้องใช้เฟรมสแต็ก Python อีกอันทำให้ค่อนข้างช้ากว่าเมธอดที่ถูกผูกไว้:
>>> def f_1():
... for x in range(1, 11):
... f(x)
...
>>> def f_2():
... for x in range(1, 11):
... divide_one_by(x)
...
>>> timeit.repeat(f_1)
[2.5495760687176485, 2.5585621018805469, 2.5411816588331888]
>>> timeit.repeat(f_2)
[3.479687248616699, 3.46196088706062, 3.473726342237768]
แน่นอนถ้าคุณสามารถใช้ตัวอักษรธรรมดานั่นก็ยิ่งเร็วขึ้น:
>>> def f_3():
... for x in range(1, 11):
... 1.0/x
...
>>> timeit.repeat(f_3)
[2.1224895628296281, 2.1219930218637728, 2.1280188256941983]
(1).__truediv__
ไม่ได้จริงๆเช่นเดียวกับ1..__truediv__
เป็นอดีตสายในขณะที่หลังไม่int.__truediv__
float.__truediv__
หรือคุณสามารถใช้1 .__truediv__
(เว้นวรรค) `