ถ้าฟังก์ชั่น A จำเป็นต้องใช้โดยฟังก์ชัน B ควรกำหนดภายใน B หรือไม่? [ปิด]


147

ตัวอย่างง่ายๆ สองวิธีวิธีหนึ่งเรียกจากวิธีอื่น:

def method_a(arg):
    some_data = method_b(arg)

def method_b(arg):
    return some_data

ในไพ ธ อนเราสามารถประกาศdefในสิ่งอื่นdefได้ ดังนั้นหากmethod_bจำเป็นและเรียกร้องเท่านั้นmethod_aฉันควรประกาศmethod_bภายในmethod_aหรือไม่ แบบนี้ :

def method_a(arg):

    def method_b(arg):
        return some_data

    some_data = method_b(arg)

หรือฉันควรหลีกเลี่ยงการทำเช่นนี้?


7
คุณไม่จำเป็นต้องกำหนดฟังก์ชั่นภายในฟังก์ชั่นอื่นนอกจากว่าคุณกำลังทำอะไรที่ขี้ขลาดจริงๆ อย่างไรก็ตามโปรดอธิบายอย่างละเอียดเกี่ยวกับสิ่งที่คุณพยายามทำเพื่อให้เราสามารถให้คำตอบที่เป็นประโยชน์มากขึ้น
inspectorG4dget

6
คุณรู้ไหมว่าตัวอย่างที่สองคือการที่แตกต่างกันเพราะคุณไม่โทร method_b ? (@inspector: คุณจำเป็นต้องพูดอย่างเคร่งครัด แต่มันมีประโยชน์อย่างมากเมื่อคุณเข้าโปรแกรมการทำงานเล็กน้อยโดยเฉพาะอย่างยิ่งการปิด)

3
@delnan: ฉันคิดว่าคุณหมายถึง "คุณไม่จำเป็นต้องพูดอย่างเคร่งครัด แต่ ... "
martineau

4
กรณีการใช้งานฟังก์ชั่นภายในมีรายละเอียดที่เยี่ยมยอดในการเชื่อมโยง: https://realpython.com/blog/python/inner-functions-what-are-they-good-for/ หากการใช้งานของคุณไม่พอดีกับกรณีใด ๆ ให้หลีกเลี่ยงการใช้งานได้ดีกว่า

1
เป็นคำถามที่ดี แต่ไม่มีคำตอบที่แท้จริงตามที่ปรากฏ ...
Mayou36

คำตอบ:


136
>>> def sum(x, y):
...     def do_it():
...             return x + y
...     return do_it
... 
>>> a = sum(1, 3)
>>> a
<function do_it at 0xb772b304>
>>> a()
4

นี่คือสิ่งที่คุณกำลังมองหา? มันเรียกว่าปิด


14
นี่เป็นคำอธิบายที่ดีกว่ามาก ฉันได้ลบคำตอบของฉันแล้ว
pyfunc

ทำไมไม่รวม def (x, y): return x + y
มะม่วง

4
@mango: นี่เป็นเพียงตัวอย่างของเล่นในการถ่ายทอดแนวคิด - ในการใช้งานจริงสิ่งที่do_it()ไม่น่าจะซับซ้อนกว่าสิ่งที่สามารถจัดการโดยเลขคณิตบางอย่างในreturnงบเดียว
martineau

2
@mango ตอบคำถามของคุณด้วยตัวอย่างที่มีประโยชน์มากกว่านี้เล็กน้อย stackoverflow.com/a/24090940/2125392
CivFan

10
ไม่ตอบคำถาม
Hunsu

49

คุณไม่ได้ประโยชน์มากนักจากการทำสิ่งนี้จริงๆแล้วมันช้าmethod_aลงเพราะมันจะกำหนดและคอมไพล์ฟังก์ชั่นอื่น ๆ ทุกครั้งที่มันถูกเรียก ระบุว่ามันน่าจะดีกว่าเพียงแค่เติมหน้าชื่อฟังก์ชันด้วยเครื่องหมายขีดล่างเพื่อระบุว่าเป็นวิธีส่วนตัว - เช่น_method_bคือ

ฉันคิดว่าคุณอาจต้องการทำเช่นนี้หากคำจำกัดความของฟังก์ชันซ้อนกันแตกต่างกันไปในแต่ละครั้งด้วยเหตุผลบางอย่าง แต่นั่นอาจบ่งบอกถึงข้อบกพร่องในการออกแบบของคุณ ที่กล่าวว่ามีเป็นเหตุผลที่ถูกต้องที่จะทำนี้เพื่อให้ฟังก์ชั่นที่ซ้อนกันที่จะใช้ข้อโต้แย้งที่ถูกส่งผ่านไปยังฟังก์ชั่นด้านนอก แต่ไม่ผ่านอย่างชัดเจนในพวกเขาซึ่งบางครั้งเกิดขึ้นเมื่อการเขียนตกแต่งฟังก์ชั่นเช่น มันเป็นสิ่งที่แสดงในคำตอบที่ยอมรับแม้ว่ามัณฑนากรจะไม่ถูกกำหนดหรือใช้

ปรับปรุง:

ต่อไปนี้เป็นข้อพิสูจน์ว่าการทำรังช้ากว่า (โดยใช้ Python 3.6.1) แม้ว่าจะไม่ค่อยได้รับการยอมรับมากนักในกรณีเล็กน้อยนี้

setup = """
class Test(object):
    def separate(self, arg):
        some_data = self._method_b(arg)

    def _method_b(self, arg):
        return arg+1

    def nested(self, arg):

        def method_b2(self, arg):
            return arg+1

        some_data = method_b2(self, arg)

obj = Test()
"""
from timeit import Timer
print(min(Timer(stmt='obj.separate(42)', setup=setup).repeat()))  # -> 0.24479823284461724
print(min(Timer(stmt='obj.nested(42)', setup=setup).repeat()))    # -> 0.26553459700452575

หมายเหตุผมเพิ่มบางselfข้อโต้แย้งฟังก์ชั่นตัวอย่างของคุณจะทำให้พวกเขามากขึ้นเช่นวิธีการจริง (ถึงแม้จะmethod_b2ยังไม่ได้เป็นเทคนิควิธีการที่Testชั้น) นอกจากนี้ฟังก์ชั่นที่ซ้อนกันจริงเรียกว่าในรุ่นที่แตกต่างจากคุณ


21
จริงๆแล้วมันไม่ได้รวบรวมฟังก์ชั่นด้านในอย่างเต็มที่ทุกครั้งที่ฟังก์ชั่นด้านนอกเรียกว่าแม้ว่ามันจะต้องสร้างวัตถุฟังก์ชั่นซึ่งใช้เวลาเล็กน้อย ในทางกลับกันชื่อฟังก์ชั่นจะกลายเป็นชื่อท้องถิ่นค่อนข้างทั่วโลกดังนั้นจึงเร็วกว่าที่จะเรียกใช้ฟังก์ชัน ในการทดลองของฉันเวลาที่ชาญฉลาดนั้นโดยทั่วไปจะเป็นการล้างเวลาส่วนใหญ่ มันอาจจะเร็วขึ้นด้วยฟังก์ชั่นด้านในถ้าคุณเรียกมันหลายครั้ง
kindall

7
ใช่คุณจะต้องใช้การเรียกหลายฟังก์ชั่นด้านใน หากคุณกำลังโทรหาแบบวนซ้ำหรือมากกว่าหนึ่งครั้งข้อดีของการมีชื่อโลคอลสำหรับฟังก์ชั่นจะเริ่มมีค่ามากกว่าค่าใช้จ่ายในการสร้างฟังก์ชั่น ในการทดลองของฉันสิ่งนี้จะเกิดขึ้นเมื่อคุณเรียกใช้ฟังก์ชันภายในประมาณ 3-4 ครั้ง แน่นอนว่าคุณสามารถได้รับประโยชน์แบบเดียวกัน (โดยไม่ต้องเสียค่าใช้จ่ายมากนัก) โดยการกำหนดชื่อท้องถิ่นสำหรับฟังก์ชั่นเช่นmethod_b = self._method_bจากนั้นเรียกmethod_bเพื่อหลีกเลี่ยงการค้นหาคุณสมบัติซ้ำ (เกิดขึ้นที่ฉันทำสิ่งต่าง ๆ มากมายเมื่อเร็ว ๆ นี้ :)
kindall

3
@kindall: ใช่นั่นเป็นเรื่องจริง ฉันแก้ไขการทดสอบเวลาของฉันดังนั้นมันจึงทำการโทร 30 ครั้งไปยังฟังก์ชั่นที่สองและผลการหมุน ฉันจะลบคำตอบของฉันหลังจากที่คุณมีโอกาสเห็นคำตอบนี้ ขอบคุณสำหรับการตรัสรู้
martineau

2
แค่อยากจะอธิบาย -1 ของฉันเพราะนี่เป็นคำตอบที่ให้ข้อมูล: ฉันให้ -1 นี่เพราะมันมุ่งเน้นไปที่ความแตกต่างของประสิทธิภาพเล็กน้อย (ในสถานการณ์ส่วนใหญ่การสร้างวัตถุรหัสจะใช้เวลาเพียงเศษเสี้ยวของเวลาดำเนินการของฟังก์ชัน ) สิ่งสำคัญที่ต้องพิจารณาในกรณีเหล่านี้คือการมีฟังก์ชั่นแบบอินไลน์สามารถปรับปรุงความสามารถในการอ่านและบำรุงรักษาโค้ดซึ่งฉันคิดว่าบ่อยครั้งเพราะคุณไม่จำเป็นต้องค้นหา / เลื่อนดูไฟล์เพื่อค้นหารหัสที่เกี่ยวข้อง
Blixt

2
@ Blixt: ฉันคิดว่าตรรกะของคุณมีข้อบกพร่อง (และลงคะแนนไม่ยุติธรรม) เพราะมันไม่น่าเป็นไปได้อย่างยิ่งที่วิธีการอื่นในชั้นเรียนเดียวกันจะ "ไกล" จากที่อื่นในชั้นเรียนเดียวกันแม้ว่ามันจะไม่ซ้อนกัน เป็นไฟล์อื่น) อีกทั้งประโยคแรกในคำตอบของฉันคือ "คุณไม่ได้ประโยชน์มากนักจากการทำเช่นนี้" ซึ่งชี้ให้เห็นว่ามันเป็นความแตกต่างเล็กน้อย
martineau

27

ฟังก์ชั่นภายในของฟังก์ชั่นที่ใช้กันทั่วไปสำหรับการปิดการปิด

(มีเป็นจำนวนมากของการต่อสู้มากกว่าว่าสิ่งที่ทำให้ปิดปิด )

นี่คือตัวอย่างการใช้งานในsum()ตัว มันกำหนดstartเพียงครั้งเดียวและใช้มันจากนั้นใน:

def sum_partial(start):
    def sum_start(iterable):
        return sum(iterable, start)
    return sum_start

ในการใช้งาน:

>>> sum_with_1 = sum_partial(1)
>>> sum_with_3 = sum_partial(3)
>>> 
>>> sum_with_1
<function sum_start at 0x7f3726e70b90>
>>> sum_with_3
<function sum_start at 0x7f3726e70c08>
>>> sum_with_1((1,2,3))
7
>>> sum_with_3((1,2,3))
9

การปิดตัวหลามแบบในตัว

functools.partial เป็นตัวอย่างของการปิด

จากเอกสารหลามมันเทียบเท่ากับ:

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

(คำชื่นชมถึง @ user225312 ด้านล่างสำหรับคำตอบฉันคิดว่าตัวอย่างนี้ง่ายกว่าที่จะคิดออกและหวังว่าจะช่วยตอบความคิดเห็นของ @ mango)


-1 ใช่พวกมันถูกใช้เป็นตัวปิด ตอนนี้อ่านคำถามอีกครั้ง โดยทั่วไปเขาถามว่าแนวคิดที่เขาแสดงสามารถใช้เป็นกรณี b ได้หรือไม่ บอกเขาว่าสิ่งนี้มักจะใช้สำหรับกรณี a ไม่ใช่คำตอบที่ไม่ดี แต่เป็นคำตอบที่ผิดสำหรับคำถามนี้ เขาสนใจว่ามันเป็นเรื่องดีหรือไม่ที่จะทำตามที่กล่าวมาข้างต้นสำหรับการห่อหุ้มตัวอย่างเช่น
Mayou36

@ Mayou36 เพื่อความเป็นธรรมคำถามนี้ค่อนข้างเปิดกว้าง - แทนที่จะพยายามตอบทุกกรณีที่เป็นไปได้ฉันคิดว่ามันจะดีที่สุดที่จะมุ่งเน้น คำถามก็ไม่ชัดเจนเช่นกัน ตัวอย่างเช่นมันบ่งบอกถึงการปิดตัวลงในตัวอย่างที่สองแม้ว่าจะไม่ใช่สิ่งที่ตั้งใจ
CivFan

@ Mayou36 "โดยทั่วไปเขาถามว่าแนวคิดที่เขาแสดงสามารถใช้เป็นกรณี b ได้หรือไม่" ไม่คำถามถามว่าควรใช้หรือไม่ OP ทราบแล้วว่าสามารถใช้งานได้
CivFan

1
ดี "ถ้า method_b เป็นสิ่งจำเป็นสำหรับและเรียกใช้เฉพาะจาก method_a ฉันควรประกาศ method_b ภายใน method_a หรือไม่" ค่อนข้างชัดเจนและไม่มีส่วนเกี่ยวข้องกับการปิดใช่ไหม ใช่ฉันยอมรับผมใช้กระป๋องในทางของควร แต่นั่นไม่เกี่ยวกับการปิด ... ฉันแค่แปลกใจที่คำตอบมากมายเกี่ยวกับการปิดและวิธีการใช้เมื่อ OP ถามคำถามที่แตกต่างอย่างสิ้นเชิง
Mayou36

@ Mayou36 มันอาจช่วยให้คุณตั้งคำถามใหม่ว่าคุณเห็นมันอย่างไรและเปิดคำถามอื่นขึ้นมาเพื่อตอบคำถาม
CivFan

17

โดยทั่วไปไม่ไม่ได้กำหนดฟังก์ชั่นภายในฟังก์ชั่น

ถ้าคุณไม่มีเหตุผลที่ดีจริงๆ ซึ่งคุณทำไม่ได้

ทำไมจะไม่ล่ะ?

อะไรคือเหตุผลที่ดีในการกำหนดฟังก์ชั่นภายในฟังก์ชั่น?

เมื่อสิ่งที่คุณจริงต้องการคือ dingdang ปิด


1
คำตอบนี้สำหรับคุณ @ Mayou36
CivFan

2
ใช่ขอบคุณนี่คือคำตอบที่ฉันต้องการ วิธีนี้จะตอบคำถามในวิธีที่ดีที่สุดเท่าที่จะทำได้ แม้ว่ามันจะไม่พูดอย่างใดอย่างหนึ่งอย่างใดอย่างหนึ่ง แต่มันก็ทำให้หมดกำลังใจมากคำจำกัดความแบบอินไลน์โดยระบุเหตุผล นั่นเป็นวิธีที่คำตอบ (pythonic :)) ควรจะเป็น!
Mayou36

10

เป็นเรื่องปกติที่จะประกาศฟังก์ชันหนึ่งในอีกฟังก์ชันหนึ่ง นี่คือการสร้างตกแต่งที่มีประโยชน์เป็นพิเศษ

อย่างไรก็ตามตามกฎทั่วไปหากฟังก์ชันซับซ้อน (มากกว่า 10 บรรทัด) อาจเป็นความคิดที่ดีที่จะประกาศในระดับโมดูล


2
เป็นไปได้ แต่ฉันเห็นด้วยคุณต้องมีเหตุผลที่ดีสำหรับการทำมัน มันจะเป็นงูหลามมากขึ้นที่จะใช้ขีดล่างก่อนหน้าสำหรับฟังก์ชั่นที่ตั้งใจจะใช้เฉพาะในชั้นเรียนของคุณ
chmullig

3
ภายในชั้นเรียนใช่ แต่สิ่งที่เกี่ยวกับภายในฟังก์ชั่นเท่านั้น? การห่อหุ้มนั้นเป็นแบบลำดับชั้น
พอลเดรเปอร์

@PaulDraper "Encapsulation is hierarchical" - ไม่! ใครบอกว่า การห่อหุ้มเป็นหลักการที่กว้างกว่าการถ่ายทอดทางพันธุกรรม
Mayou36

7

ฉันพบคำถามนี้เพราะฉันต้องการตั้งคำถามว่าทำไมมีผลกระทบต่อประสิทธิภาพหากใช้ฟังก์ชันซ้อนกัน ฉันทดสอบการใช้งานฟังก์ชั่นต่อไปนี้โดยใช้ Python 3.2.5 ใน Windows Notebook พร้อมโปรเซสเซอร์ Quad Core 2.5 GHz Intel i5-2530M

def square0(x):
    return x*x

def square1(x):
    def dummy(y):
        return y*y
    return x*x

def square2(x):
    def dummy1(y):
        return y*y
    def dummy2(y):
        return y*y
    return x*x

def square5(x):
    def dummy1(y):
        return y*y
    def dummy2(y):
        return y*y
    def dummy3(y):
        return y*y
    def dummy4(y):
        return y*y
    def dummy5(y):
        return y*y
    return x*x

ฉันวัด 20 ครั้งต่อไปนี้สำหรับสแควร์ 1, สแควร์ 2 และสแควร์ 5:

s=0
for i in range(10**6):
    s+=square0(i)

และได้ผลลัพธ์ดังต่อไปนี้

>>> 
m = mean, s = standard deviation, m0 = mean of first testcase
[m-3s,m+3s] is a 0.997 confidence interval if normal distributed

square? m     s       m/m0  [m-3s ,m+3s ]
square0 0.387 0.01515 1.000 [0.342,0.433]
square1 0.460 0.01422 1.188 [0.417,0.503]
square2 0.552 0.01803 1.425 [0.498,0.606]
square5 0.766 0.01654 1.979 [0.717,0.816]
>>> 

square0ไม่มีฟังก์ชั่นที่ซ้อนกันsquare1มีฟังก์ชั่นที่ซ้อนกันหนึ่งฟังก์ชั่นที่square2ซ้อนกันสองฟังก์ชั่นและsquare5มีห้าฟังก์ชั่นที่ซ้อนกัน ฟังก์ชั่นที่ซ้อนกันจะประกาศเท่านั้น แต่ไม่ได้เรียก

ดังนั้นหากคุณกำหนดฟังก์ชั่นซ้อนกัน 5 อันในฟังก์ชั่นที่คุณไม่ได้เรียกใช้เวลาในการดำเนินการของฟังก์ชั่นจะเป็นสองเท่าของฟังก์ชั่นที่ไม่มีฟังก์ชั่นซ้อนอยู่ ฉันคิดว่าควรระมัดระวังเมื่อใช้ฟังก์ชั่นที่ซ้อนกัน

แฟ้มงูใหญ่สำหรับการทดสอบทั้งที่สร้างผลลัพธ์นี้สามารถพบได้ที่ideone


5
การเปรียบเทียบที่คุณทำไม่มีประโยชน์จริงๆ มันเหมือนกับการเพิ่มข้อความจำลองเข้าไปในฟังก์ชันและบอกว่าช้าลง ตัวอย่างของมาร์ติโนใช้ฟังก์ชั่นที่ห่อหุ้มและฉันไม่สังเกตเห็นความแตกต่างของประสิทธิภาพโดยการใช้ตัวอย่างของเขา
kon Psych

-1 โปรดอ่านคำถามอีกครั้ง แม้ว่าคุณอาจจะบอกว่ามันอาจช้าลงเล็กน้อยเขาถามว่ามันเป็นความคิดที่ดีที่จะทำไม่ใช่เป็นเพราะประสิทธิภาพ แต่เป็นเรื่องทั่วไป
Mayou36

@ Mayou36 ขออภัยสามปีหลังจากคำถามและคำตอบถูกโพสต์ฉันจะไม่
miracle173

ตกลงขออภัยยังไม่มีคำตอบ (หรือดี) ที่ยอมรับได้
Mayou36

4

เป็นเพียงหลักการเกี่ยวกับ API การเปิดเผย

การใช้ python เป็นความคิดที่ดีที่จะหลีกเลี่ยงการสัมผัส API ในอวกาศ (โมดูลหรือคลาส) ฟังก์ชั่นเป็นสถานที่ที่ดีในการห่อหุ้ม

มันอาจเป็นความคิดที่ดี เมื่อคุณมั่นใจ

  1. ฟังก์ชั่นด้านในเท่านั้นที่ใช้โดยฟังก์ชั่นด้านนอก
  2. ฟังก์ชั่นภายในมีชื่อที่ดีที่จะอธิบายวัตถุประสงค์ของมันเพราะรหัสพูด
  3. รหัสไม่สามารถเข้าใจได้โดยตรงจากเพื่อนร่วมงานของคุณ (หรือเครื่องอ่านรหัสอื่น ๆ )

แม้ว่าการใช้ผิดวิธีเทคนิคนี้อาจทำให้เกิดปัญหาและแสดงถึงข้อบกพร่องในการออกแบบ

เพียงจากประสบการณ์ของฉันอาจเข้าใจผิดคำถามของคุณ


4

ดังนั้นในท้ายที่สุดคำถามส่วนใหญ่เกี่ยวกับการใช้งานไพ ธ อนของสมาร์ทอย่างฉลาดหรือไม่โดยเฉพาะอย่างยิ่งในกรณีของฟังก์ชั่นด้านในไม่ใช่การปิด แต่ก็เป็นเพียงผู้ช่วยที่ต้องการ

ในการออกแบบที่เข้าใจได้ง่ายที่มีฟังก์ชั่นเฉพาะที่จำเป็นและไม่ได้สัมผัสที่อื่นคือการออกแบบที่ดีไม่ว่าจะฝังอยู่ในโมดูลคลาสเป็นวิธีหรือภายในฟังก์ชันหรือวิธีอื่น เมื่อทำดีแล้วพวกเขาปรับปรุงความชัดเจนของรหัส

และเมื่อฟังก์ชั่นด้านในเป็นการปิดที่ยังสามารถช่วยให้มีความชัดเจนค่อนข้างน้อยแม้ว่าฟังก์ชั่นนั้นจะไม่ถูกส่งกลับจากฟังก์ชั่นที่มีอยู่เพื่อใช้งานที่อื่น

ดังนั้นฉันจะบอกว่าโดยทั่วไปจะใช้พวกเขา แต่ระวังประสิทธิภาพที่เป็นไปได้เมื่อคุณกังวลเกี่ยวกับประสิทธิภาพและลบออกเฉพาะเมื่อคุณทำโปรไฟล์จริงที่แสดงให้เห็นว่าพวกเขาถูกลบออกดีที่สุด

อย่าเพิ่มประสิทธิภาพก่อนวัยอันควรเพียงแค่ใช้ "ฟังก์ชั่นด้านใน BAD" ตลอดรหัสหลามทั้งหมดที่คุณเขียน กรุณา.


ดังที่แสดงโดยคำตอบอื่น ๆ คุณไม่ได้มีผลการดำเนินงานยอดเยี่ยมจริงๆ
Mayou36

1

เป็นเรื่องที่ดีที่จะทำแบบนั้น แต่ถ้าคุณไม่จำเป็นต้องใช้การปิดหรือส่งคืนฟังก์ชั่นที่ฉันอาจจะใส่ไว้ในระดับโมดูล ฉันจินตนาการในตัวอย่างโค้ดที่สองที่คุณหมายถึง:

...
some_data = method_b() # not some_data = method_b

มิฉะนั้น some_data จะเป็นฟังก์ชั่น

การมีระดับโมดูลจะทำให้ฟังก์ชั่นอื่นใช้ method_b () และถ้าคุณใช้บางอย่างเช่นสฟิงซ์ (และ autodoc) สำหรับเอกสารประกอบก็จะช่วยให้คุณทำเอกสาร method_b เช่นกัน

คุณอาจต้องการพิจารณาเพียงแค่วางฟังก์ชันการทำงานในสองวิธีในชั้นเรียนหากคุณกำลังทำบางสิ่งที่สามารถเป็นตัวแทนของวัตถุได้ สิ่งนี้มีเหตุผลเช่นกันหากนั่นคือทั้งหมดที่คุณต้องการ


1

ทำสิ่งที่ชอบ:

def some_function():
    return some_other_function()
def some_other_function():
    return 42 

ถ้าคุณต้องการเรียกใช้some_function()มันก็จะรันsome_other_function()และส่งคืน 42

แก้ไข: ฉันเดิมกล่าวว่าคุณไม่ควรกำหนดฟังก์ชั่นภายในของอื่น แต่มันก็ชี้ให้เห็นว่ามันเป็นประโยชน์ในการทำเช่นนี้บางครั้ง


ฉันซาบซึ้งในความพยายามที่ได้กล่าวมาข้างต้น แต่คุณได้รับคำสั่งและตรงประเด็น ดี
C0NFUS3D

1
ทำไม? ทำไมคุณไม่ควรทำอย่างนั้น? การห่อหุ้มนั้นยอดเยี่ยมใช่ไหม ฉันไม่มีข้อโต้แย้งใด ๆ -1
Mayou36

@ Mayou36 ฉันไม่ทราบว่าการห่อหุ้มคืออะไรในขณะที่เขียนความคิดเห็นของฉันและฉันก็ไม่รู้ว่ามันคืออะไรในตอนนี้ ฉันแค่คิดว่ามันไม่ดีที่จะทำ คุณช่วยอธิบายได้ไหมว่าทำไมจึงเป็นประโยชน์ในการกำหนดฟังก์ชั่นภายในอีกฟังก์ชันหนึ่งแทนที่จะกำหนดไว้นอกฟังก์ชั่น?
mdlp0716

2
ใช่ฉันทำได้. คุณอาจค้นหาแนวคิดของการห่อหุ้ม แต่ในระยะสั้น: ซ่อนข้อมูลที่ไม่จำเป็นและเปิดเผยให้ผู้ใช้เห็นสิ่งที่จำเป็นต้องรู้เท่านั้น ซึ่งหมายความว่าการนิยาม some_other_function ภายนอกเพียงเพิ่มบางสิ่งลงในเนมสเปซซึ่งจริงๆแล้วถูกผูกไว้กับฟังก์ชันแรกอย่างแน่นหนา หรือคิดในแง่ของตัวแปร: ทำไมคุณถึงต้องการตัวแปรท้องถิ่นเทียบกับตัวแปรทั่วโลก การกำหนดตัวแปรทั้งหมดภายในฟังก์ชั่นถ้าเป็นไปได้ดีกว่าแล้วใช้ตัวแปรทั่วโลกสำหรับตัวแปรที่ใช้ภายในฟังก์ชั่นนี้เท่านั้น มันคือทั้งหมดที่เกี่ยวกับการลดความซับซ้อนในที่สุด
Mayou36

0

คุณสามารถใช้มันเพื่อหลีกเลี่ยงการกำหนดตัวแปรส่วนกลาง นี่เป็นทางเลือกสำหรับการออกแบบอื่น ๆ 3 การออกแบบนำเสนอวิธีแก้ไขปัญหา

A) การใช้ฟังก์ชั่นโดยไม่ต้องกลม

def calculate_salary(employee, list_with_all_employees):
    x = _calculate_tax(list_with_all_employees)

    # some other calculations done to x
    pass

    y = # something 

    return y

def _calculate_tax(list_with_all_employees):
    return 1.23456 # return something

B) การใช้ฟังก์ชั่นที่มีกลม

_list_with_all_employees = None

def calculate_salary(employee, list_with_all_employees):

    global _list_with_all_employees
    _list_with_all_employees = list_with_all_employees

    x = _calculate_tax()

    # some other calculations done to x
    pass

    y = # something

    return y

def _calculate_tax():
    return 1.23456 # return something based on the _list_with_all_employees var

C) การใช้ฟังก์ชั่นภายในฟังก์ชั่นอื่น

def calculate_salary(employee, list_with_all_employees):

    def _calculate_tax():
        return 1.23456 # return something based on the list_with_a--Lemployees var

    x = _calculate_tax()

    # some other calculations done to x
    pass
    y = # something 

    return y

โซลูชันC)อนุญาตให้ใช้ตัวแปรในขอบเขตของฟังก์ชันภายนอกโดยไม่จำเป็นต้องประกาศตัวแปรเหล่านั้นในฟังก์ชันภายใน อาจมีประโยชน์ในบางสถานการณ์


0

ฟังก์ชั่นในฟังก์ชั่นหลาม

def Greater(a,b):
    if a>b:
        return a
    return b

def Greater_new(a,b,c,d):
    return Greater(Greater(a,b),Greater(c,d))

print("Greater Number is :-",Greater_new(212,33,11,999))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.