Python - tại sao lại sử dụng “self” trong một lớp?


82

2 lớp này khác nhau như thế nào?

class A():
    x=3

class B():
    def __init__(self):
        self.x=3

Có sự khác biệt đáng kể nào không?


6
không, nó không phải là một bản sao.

1
@hop: Khẳng định thú vị, nhưng bạn chưa cung cấp bất kỳ ví dụ hoặc bằng chứng nào cho thấy nó không phải là một bản sao. tại sao bạn nói như vậy?
S.Lott

2
@ S.Lott - Hả? Câu hỏi khác là đặt ra câu hỏi tại sao chúng ta cần vượt qua bản thân một cách rõ ràng. Đây là câu hỏi về sự khác biệt bởi vì các biến lớp và phiên bản.
Dana

1
@ S.Lott Đó không phải là câu hỏi tương tự. Tôi thậm chí đã nhìn vào cái đó trước khi hỏi nó.
ryeguy

2
@ S.Lott: 68282 là một câu hỏi vô ích về việc tại sao bạn phải đặt mình một cách rõ ràng là đối số đầu tiên cho các phương thức; câu hỏi này hỏi về sự khác biệt giữa các thành viên lớp và cá thể. S.Lott, tôi thực sự thích những đóng góp của bạn cho SO, nhưng lần này bạn đã nhầm.

Câu trả lời:


137

A.xlà một biến lớp . B's self.xlà một biến thể hiện .

tức là A's xđược chia sẻ giữa các trường.

Sẽ dễ dàng hơn để chứng minh sự khác biệt với một cái gì đó có thể được sửa đổi như danh sách:

#!/usr/bin/env python

class A:
    x = []
    def add(self):
        self.x.append(1)

class B:
    def __init__(self):
        self.x = []
    def add(self):
        self.x.append(1)

x = A()
y = A()
x.add()
y.add()
print("A's x:", x.x)

x = B()
y = B()
x.add()
y.add()
print("B's x:", x.x)

Đầu ra

A's x: [1, 1]
B's x: [1]

8
Có lẽ cũng gửi đầu ra của kịch bản của bạn, sau đó người ta có thể thấy sự khác biệt mà không cần sao chép và chạy nó chính mình ...
Martin

7
Tôi đã thêm đầu ra.
UnkwnTech

2
Sau đó, bản thân của python có tương đương với Java không? Xin lỗi các xin noobishness
Jean Azzopardi

2
@Jean - Yes-ish - self chỉ phải là tên quy ước được đặt cho tham số đầu tiên của các phương thức instance - và python chuyển rõ ràng phiên bản hiện tại của các phương thức instance làm đối số đầu tiên cho các phương thức instance. Nhưng nó hiện công việc tương tự như Java là này
Douglas Leeder

@Jean Azzopardi: bản thân gần giống như Java (và c ++) cái này. Bản thân chỉ đơn giản là bắt buộc; điều này đôi khi được giải thích bởi trình biên dịch Java (những lúc khác thì nó được yêu cầu.)
S.Lott

55

Cũng giống như một mặt lưu ý: selftrên thực tế chỉ là một từ được lựa chọn một cách ngẫu nhiên, mà sử dụng tất cả mọi người, nhưng bạn cũng có thể sử dụng this, foohoặc myselfhoặc bất cứ điều gì khác mà bạn muốn, nó chỉ là tham số đầu tiên của mỗi phương pháp phi tĩnh cho một lớp học. Điều này có nghĩa là từ selfkhông phải là một cấu trúc ngôn ngữ mà chỉ là một cái tên:

>>> class A:
...     def __init__(s):
...        s.bla = 2
... 
>>> 
>>> a = A()
>>> a.bla
2

1
Tại sao đây là câu trả lời mà không phải là bình luận
Gabriel Petersson

23

Ax là một biến lớp và sẽ được chia sẻ trên tất cả các phiên bản của A, trừ khi được ghi đè cụ thể trong một phiên bản. Bx là một biến thể hiện và mỗi thể hiện của B có phiên bản riêng của nó.

Tôi hy vọng ví dụ Python sau có thể làm rõ:


    >>> class Foo():
    ...     i = 3
    ...     def bar(self):
    ...             print 'Foo.i is', Foo.i
    ...             print 'self.i is', self.i
    ... 
    >>> f = Foo() # Create an instance of the Foo class
    >>> f.bar()
    Foo.i is 3
    self.i is 3
    >>> Foo.i = 5 # Change the global value of Foo.i over all instances
    >>> f.bar()
    Foo.i is 5
    self.i is 5
    >>> f.i = 3 # Override this instance's definition of i
    >>> f.bar()
    Foo.i is 5
    self.i is 3

16

Tôi đã từng giải thích nó bằng ví dụ này

# By TMOTTM

class Machine:

    # Class Variable counts how many machines have been created.
    # The value is the same for all objects of this class.
    counter = 0

    def __init__(self):

        # Notice: no 'self'.
        Machine.counter += 1

        # Instance variable.
        # Different for every object of the class.
        self.id = Machine.counter

if __name__ == '__main__':
    machine1 = Machine()
    machine2 = Machine()
    machine3 = Machine()

    #The value is different for all objects.
    print 'machine1.id', machine1.id
    print 'machine2.id', machine2.id
    print 'machine3.id', machine3.id

    #The value is the same for all objects.
    print 'machine1.counter', machine1.counter
    print 'machine2.counter', machine2.counter
    print 'machine3.counter', machine3.counter

Đầu ra sau đó sẽ bằng

machine1.id 1
machine2.id 2
machine3.id 3

machine1.counter 3
machine2.counter 3
machine3.counter 3

3

Tôi vừa mới bắt đầu học Python và điều này cũng khiến tôi bối rối trong một thời gian. Cố gắng tìm ra cách tất cả hoạt động nói chung, tôi đã nghĩ ra đoạn mã rất đơn giản này:

# Create a class with a variable inside and an instance of that class
class One:
    color = 'green'

obj2 = One()


# Here we create a global variable(outside a class suite).
color = 'blue'         

# Create a second class and a local variable inside this class.       
class Two:             
    color = "red"

    # Define 3 methods. The only difference between them is the "color" part.
    def out(self):     
        print(self.color + '!')

    def out2(self):
        print(color + '!')

    def out3(self):
        print(obj2.color + '!')

# Create an object of the class One
obj = Two()

Khi chúng tôi gọi, out()chúng tôi nhận được:

>>> obj.out()

red!

Khi chúng tôi gọi out2():

>>> obj.out2()

blue!

Khi chúng tôi gọi out3():

>>> obj.out3()

green!

Vì vậy, trong phương thức đầu tiên selfchỉ định rằng Python nên sử dụng biến (thuộc tính), "thuộc tính" của đối tượng lớp mà chúng ta đã tạo, không phải là toàn cục (bên ngoài lớp). Vì vậy, nó sử dụng color = "red". Trong phương thức Python thay thế hoàn toàn selfcho tên của một đối tượng mà chúng ta đã tạo ( obj). self.colorcó nghĩa là "Tôi nhận được color="red"từ obj"

Trong phương thức thứ hai, không có selfchỉ định đối tượng mà màu sẽ được lấy từ đâu, vì vậy nó sẽ lấy màu toàn cục color = 'blue'.

Trong phương pháp thứ ba thay vì selfchúng tôi đã sử dụng obj2- tên của một đối tượng khác để lấy colortừ đó. Nó được color = 'green'.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.