Hướng dẫn what is a function defined inside a class in python? - một hàm được định nghĩa bên trong một lớp trong python là gì?

Giải pháp TestBook EDU Pvt. Ltd.

Tầng 1 & 2, Tòa nhà Zion, Lô số 273, Khu vực 10, Kharghar, Navi Mumbai - 410210
Plot No. 273, Sector 10, Kharghar,
Navi Mumbai - 410210

[email protected]

Miễn phí: 1800 833 0800

Giờ làm việc: 10 giờ sáng đến 7 giờ tối [tất cả 7 ngày]

Edit::

Xem câu trả lời đầy đủ của tôi ở cuối câu hỏi này.

TL; DR Trả lời: Python có phạm vi lồng nhau tĩnh. Khía cạnh tĩnh có thể tương tác với các khai báo biến ẩn, mang lại kết quả không rõ ràng.: Python has statically nested scopes. The static aspect can interact with the implicit variable declarations, yielding non-obvious results.

[Điều này có thể đặc biệt đáng ngạc nhiên vì bản chất năng động của ngôn ngữ].

Tôi nghĩ rằng tôi đã xử lý khá tốt về các quy tắc phạm vi của Python, nhưng vấn đề này đã bị cản trở hoàn toàn, và Google -Fu của tôi đã làm tôi thất bại [không phải là tôi ngạc nhiên - hãy nhìn vào tiêu đề câu hỏi;]

Tôi sẽ bắt đầu với một vài ví dụ hoạt động như mong đợi, nhưng hãy bỏ qua ví dụ 4 cho phần ngon ngọt.

Ví dụ 1.

>>> x = 3
>>> class MyClass[object]:
...     x = x
... 
>>> MyClass.x
3

Đủ đơn giản: Trong quá trình định nghĩa lớp học, chúng tôi có thể truy cập các biến được xác định trong phạm vi bên ngoài [trong trường hợp này là toàn cầu].

Ví dụ 2.

>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3

Một lần nữa [bỏ qua hiện tại tại sao người ta có thể muốn làm điều này], không có gì bất ngờ ở đây: chúng ta có thể truy cập các chức năng trong phạm vi bên ngoài.

Lưu ý: Như Frédéric đã chỉ ra bên dưới, chức năng này dường như không hoạt động. Xem ví dụ 5 [và hơn thế nữa] thay thế.: as Frédéric pointed out below, this function doesn't seem to work. See Example 5 [and beyond] instead.

Ví dụ 3.

>>> def myfunc[]:
...     x = 3
...     class MyClass[object]:
...         x = x
...     return MyClass
... 
>>> myfunc[].x
Traceback [most recent call last]:
  File "", line 1, in 
  File "", line 3, in myfunc
  File "", line 4, in MyClass
NameError: name 'x' is not defined

Điều này về cơ bản giống như ví dụ 1: Chúng tôi đang truy cập phạm vi bên ngoài từ trong định nghĩa lớp, chỉ là thời điểm này phạm vi không toàn cầu, nhờ

>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
3.

EDIT 5: Như @user3022222 đã chỉ ra bên dưới, tôi đã làm hỏng ví dụ này trong bài đăng gốc của mình. Tôi tin rằng điều này không thành công vì chỉ các chức năng [không phải các khối mã khác, như định nghĩa lớp này] có thể truy cập các biến trong phạm vi kèm theo. Đối với các khối mã không chức năng, chỉ có thể truy cập các biến cục bộ, toàn cầu và tích hợp. Một lời giải thích kỹ lưỡng hơn có sẵn trong câu hỏi này As @user3022222 pointed out below, I botched this example in my original posting. I believe this fails because only functions [not other code blocks, like this class definition] can access variables in the enclosing scope. For non-function code blocks, only local, global and built-in variables are accessible. A more thorough explanation is available in this question

Một lần nữa:

Ví dụ 4.

>>> def my_defining_func[]:
...     def mymethod[self]:
...         return self.y
...     class MyClass[object]:
...         mymethod = mymethod
...         y = 3
...     return MyClass
... 
>>> my_defining_func[]
Traceback [most recent call last]:
  File "", line 1, in 
  File "", line 4, in my_defining_func
  File "", line 5, in MyClass
NameError: name 'mymethod' is not defined

Ừm ... xin lỗi?

Điều gì làm cho điều này khác với ví dụ 2?

Tôi hoàn toàn bị cản trở. Xin hãy sắp xếp cho tôi. Cảm ơn!

P.S. Về cơ hội rằng đây không chỉ là vấn đề với sự hiểu biết của tôi, tôi đã thử điều này trên Python 2.5.2 và Python 2.6.2. Thật không may, đó là tất cả những gì tôi có quyền truy cập vào lúc này, nhưng cả hai đều thể hiện cùng một hành vi.

Chỉnh sửa theo //docs.python.org/tutorial/classes.html#python-scopes-and-macespaces: Bất cứ lúc nào trong quá trình thực hiện, có ít nhất ba phạm vi lồng nhau có không gian tên có thể truy cập trực tiếp: According to //docs.python.org/tutorial/classes.html#python-scopes-and-namespaces: at any time during execution, there are at least three nested scopes whose namespaces are directly accessible:

  • Phạm vi trong cùng, được tìm kiếm trước, chứa tên địa phương
  • Phạm vi của bất kỳ chức năng bao quanh nào, được tìm kiếm bắt đầu với phạm vi bao quanh gần nhất, chứa các tên không cục bộ, nhưng cũng không phải là toàn cầu
  • Phạm vi tiếp theo có chứa các tên toàn cầu hiện tại của mô-đun
  • Phạm vi ngoài cùng [được tìm kiếm cuối cùng] là không gian tên chứa tên tích hợp

#4. dường như là một ví dụ phản đối thứ hai trong số này.

Chỉnh sửa 2

Ví dụ 5.

>>> def fun1[]:
...     x = 3
...     def fun2[]:
...         print x
...     return fun2
... 
>>> fun1[][]
3

Chỉnh sửa 3

Như @frédéric đã chỉ ra việc gán cho một biến có cùng tên với phạm vi bên ngoài dường như "che dấu" biến bên ngoài, ngăn chặn việc gán hoạt động.

Vì vậy, phiên bản sửa đổi của ví dụ 4 hoạt động:

def my_defining_func[]:
    def mymethod_outer[self]:
        return self.y
    class MyClass[object]:
        mymethod = mymethod_outer
        y = 3
    return MyClass

my_defining_func[]

Tuy nhiên điều này không:

def my_defining_func[]:
    def mymethod[self]:
        return self.y
    class MyClass[object]:
        mymethod_temp = mymethod
        mymethod = mymethod_temp
        y = 3
    return MyClass

my_defining_func[]

Tôi vẫn chưa hoàn toàn hiểu tại sao mặt nạ này xảy ra: không phải ràng buộc tên xảy ra khi bài tập xảy ra?

Ví dụ này ít nhất cung cấp một số gợi ý [và một thông báo lỗi hữu ích hơn]:

>>> def my_defining_func[]:
...     x = 3
...     def my_inner_func[]:
...         x = x
...         return x
...     return my_inner_func
... 
>>> my_defining_func[][]
Traceback [most recent call last]:
  File "", line 1, in 
  File "", line 4, in my_inner_func
UnboundLocalError: local variable 'x' referenced before assignment
>>> my_defining_func[]

Vì vậy, có vẻ như biến cục bộ được xác định trong việc tạo chức năng [thành công], dẫn đến tên cục bộ là "bảo lưu" và do đó che dấu tên phạm vi bên ngoài khi hàm được gọi.

Interesting.

Cảm ơn Frédéric vì câu trả lời!

Để tham khảo, từ các tài liệu Python:

Điều quan trọng là phải nhận ra rằng phạm vi được xác định bằng văn bản: phạm vi toàn cầu của một hàm được xác định trong một mô -đun là không gian tên mô -đun, bất kể hàm bí danh nào được gọi là bí danh. Mặt khác, việc tìm kiếm thực tế cho các tên được thực hiện một cách linh hoạt, tại thời điểm chạy - tuy nhiên, định nghĩa ngôn ngữ đang phát triển theo độ phân giải tên tĩnh, tại thời điểm biên dịch, do đó, don dựa vào độ phân giải tên động! [Trong thực tế, các biến cục bộ đã được xác định tĩnh.]

Chỉnh sửa 4

Câu trả lời thực sự

Hành vi dường như khó hiểu này là do phạm vi lồng nhau của Python được định nghĩa trong PEP 227. Nó thực sự không liên quan gì đến PEP 3104.

Từ PEP 227:

Các quy tắc độ phân giải tên là điển hình cho các ngôn ngữ phạm vi thống kê [...] [ngoại trừ] các biến không được khai báo. Nếu một hoạt động liên kết tên xảy ra ở bất cứ đâu trong một hàm, thì tên đó được coi là cục bộ với hàm và tất cả các tài liệu tham khảo đều đề cập đến ràng buộc cục bộ. Nếu một tài liệu tham khảo xảy ra trước khi tên bị ràng buộc, một nameerror sẽ được nêu ra.

[...]

Một ví dụ từ Tim Peters chứng minh những cạm bẫy tiềm năng của phạm vi lồng nhau trong trường hợp không có tuyên bố:

i = 6
def f[x]:
    def g[]:
        print i
    # ...
    # skip to the next page
    # ...
    for i in x:  # ah, i *is* local to f, so this is what g sees
        pass
    g[]

Cuộc gọi đến g [] sẽ đề cập đến biến i bị ràng buộc trong f [] bằng vòng lặp cho. Nếu g [] được gọi trước khi vòng lặp được thực thi, một nameerror sẽ được nâng lên.

Cho phép chạy hai phiên bản đơn giản hơn trong ví dụ của Tim:

>>> i = 6
>>> def f[x]:
...     def g[]:
...             print i
...     # ...
...     # later
...     # ...
...     i = x
...     g[]
... 
>>> f[3]
3

Khi

>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
4 không tìm thấy
>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
5 trong phạm vi bên trong của nó, nó sẽ tự động tìm kiếm bên ngoài, tìm ra
>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
5 trong phạm vi của ________ 17, đã bị ràng buộc với
>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
8 thông qua nhiệm vụ
>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
9.

Nhưng thay đổi thứ tự hai câu cuối cùng trong

>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
7 gây ra lỗi:

>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
0

Hãy nhớ rằng PEP 227 cho biết "các quy tắc độ phân giải tên là điển hình cho các ngôn ngữ có phạm vi thống kê", hãy xem xét phiên bản C tương đương [bán] phiên bản C tương đương:

>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
1

biên dịch và chạy:

>>> def mymethod[self]:
...     return self.x
... 
>>> x = 3
>>> class MyClass[object]:
...     x = x
...     mymethod = mymethod
...
>>> MyClass[].mymethod[]
3
2

Vì vậy, trong khi C sẽ vui vẻ sử dụng một biến không liên kết [sử dụng bất cứ điều gì xảy ra đã được lưu trữ ở đó trước: 134520820, trong trường hợp này], Python [rất may] từ chối.

Là một câu chuyện phụ thú vị, phạm vi lồng nhau được cho phép mà Alex Martelli đã gọi là "Tối ưu hóa quan trọng nhất mà trình biên dịch Python thực hiện: các biến cục bộ của một hàm không được giữ trong một vectơ chặt chẽ Truy cập biến cục bộ sử dụng chỉ mục trong vectơ đó, không phải là tra cứu tên. "

Hàm là gì khi nó được xác định bên trong một lớp là gì?

Hàm thành viên của một lớp là một hàm có định nghĩa hoặc nguyên mẫu của nó trong định nghĩa lớp như bất kỳ biến nào khác.Nó hoạt động trên bất kỳ đối tượng nào của lớp mà nó là thành viên và có quyền truy cập vào tất cả các thành viên của một lớp cho đối tượng đó. of a class is a function that has its definition or its prototype within the class definition like any other variable. It operates on any object of the class of which it is a member, and has access to all the members of a class for that object.

Những gì được gọi là khi một hàm được xác định bên trong?

Khi hàm thành viên được xác định bên trong lớp, nó được gọi là hàm nội tuyến.

Chức năng xác định trong Python là gì?

Xác định các chức năng trong Python trong lập trình máy tính, một hàm là một phần được đặt tên của một mã thực hiện một nhiệm vụ cụ thể.Điều này thường liên quan đến việc lấy một số đầu vào, thao tác đầu vào và trả về đầu ra.a named section of a code that performs a specific task. This typically involves taking some input, manipulating the input and returning an output.

Bài Viết Liên Quan

Chủ Đề