__init__ และตัวเองทำอะไรกับ Python


792

ฉันเรียนรู้ภาษา Python และฉันเจอบางอย่างที่ฉันไม่เข้าใจ

ในวิธีการเช่น:

def method(self, blah):
    def __init__(?):
        ....
    ....

อะไร selfทำอย่างไร มันหมายความว่าอะไร จำเป็นหรือไม่

อะไร __init__วิธีการทำอย่างไร ทำไมถึงจำเป็น? (อื่น ๆ )

ฉันคิดว่าพวกเขาอาจเป็น OOP ที่สร้างขึ้นมา แต่ฉันไม่รู้มาก

คำตอบ:


585

ในรหัสนี้:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

... selfตัวแปรแสดงถึงอินสแตนซ์ของวัตถุเอง ภาษาเชิงวัตถุส่วนใหญ่ผ่านสิ่งนี้เป็นพารามิเตอร์ที่ซ่อนอยู่กับวิธีการที่กำหนดไว้ในวัตถุ Python ไม่ได้ คุณต้องประกาศอย่างชัดเจน เมื่อคุณสร้างอินสแตนซ์ของAคลาสและเรียกเมธอดของคลาสนั้นมันจะถูกส่งโดยอัตโนมัติเช่นเดียวกับใน ...

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

__init__วิธีเป็นสิ่งที่แสดงให้เห็นถึงประมาณคอนสตรัคในหลาม เมื่อคุณเรียกA()Python สร้างวัตถุให้คุณแล้วส่งผ่านเป็นพารามิเตอร์ตัวแรกของ__init__เมธอด พารามิเตอร์เพิ่มเติมใด ๆ (เช่นA(24, 'Hello')) จะถูกส่งเป็นอาร์กิวเมนต์ในกรณีนี้ทำให้เกิดข้อยกเว้นเนื่องจากผู้สร้างไม่ได้คาดหวัง


8
เกิดอะไรขึ้นถ้าคุณใส่initx = 'Hello'นอกแต่ในชั้นเรียน มันเหมือนกับจาวาที่มันเหมือนกันหรือมันจะกลายเป็นเหมือนตัวแปรแบบสแตติกซึ่งเริ่มต้นเพียงครั้งเดียวเท่านั้น?
Jayen

15
มันเหมือนตัวแปรคงที่ มันเริ่มต้นได้เพียงครั้งเดียวและมันใช้ได้ผ่านหรือA.x a.xโปรดทราบว่าการเอาชนะมันในคลาสเฉพาะจะไม่ส่งผลกระทบต่อฐานดังนั้นA.x = 'foo'; a.x = 'bar'; print a.x; print A.xจะพิมพ์ออกbarมาfoo
Chris B.

156
เป็นมูลค่าชี้ให้เห็นว่าอาร์กิวเมนต์แรกไม่จำเป็นต้องเรียกว่าselfมันเป็นเพียงแค่การประชุม
Henry Gomersall

13
จุดประสงค์objectในการประกาศชั้นเรียนคืออะไร? ฉันสังเกตเห็นว่าบางคลาสมีสิ่งนี้และบางอย่างไม่ได้
Chris

9
@Chris It's สำหรับ Python 2 เข้ากันได้ ใน Python 3 ไม่จำเป็นต้องสืบทอดอย่างชัดเจนobjectเพราะมันเกิดขึ้นตามค่าเริ่มต้น
Gabriel

241

ใช่คุณพูดถูก oop เหล่านี้ถูกสร้างขึ้น

__init__เป็นตัวสร้างสำหรับคลาส selfพารามิเตอร์หมายถึงอินสแตนซ์ของวัตถุ (เช่นthisใน C ++)

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

__init__วิธีการได้รับการเรียกเมื่อหน่วยความจำสำหรับวัตถุที่ถูกจัดสรร:

x = Point(1,2)

มันเป็นสิ่งสำคัญที่จะใช้selfพารามิเตอร์ภายในวิธีการของวัตถุถ้าคุณต้องการที่จะเก็บค่ากับวัตถุ ตัวอย่างเช่นถ้าคุณใช้__init__วิธีนี้:

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

ของคุณxและyพารามิเตอร์จะถูกเก็บไว้ในตัวแปรในสแต็กและจะถูกทิ้งเมื่อวิธีการ init ออกไปนอกขอบเขต การตั้งค่าตัวแปรเหล่านั้นเป็นself._xและself._yตั้งค่าตัวแปรเหล่านั้นเป็นสมาชิกของPointวัตถุ (สามารถเข้าถึงได้ตลอดอายุการใช้งานของวัตถุ)


1
ดังนั้นมีเหตุผลใดที่คุณไม่ต้องการselfอยู่ใน Constructor? ทำไมคุณถึงต้องระบุมันจะไม่ดีกว่าถ้ามันบอกเป็นนัย?
Aaron Franke

เท่าที่ฉันรู้ __ init __ ไม่ใช่ตัวสร้างมันเป็นวิธีแรกที่จะถูกดำเนินการเมื่อมีการสร้างวัตถุใด ๆ __ init __ จะใช้ในการตั้งค่าวัตถุ __ ใหม่ __ เป็นตัวสร้างในหลาม
Deepanshu

206

ตัวอย่างสั้น ๆ

ด้วยความหวังว่ามันอาจช่วยได้เล็กน้อยนี่คือตัวอย่างง่ายๆที่ฉันเคยเข้าใจถึงความแตกต่างระหว่างตัวแปรที่ประกาศภายในคลาสและตัวแปรที่ประกาศใน__init__ฟังก์ชัน:

class MyClass(object):
    i = 123
    def __init__(self):
        self.i = 345

a = MyClass()
print(a.i)
print(MyClass.i)

เอาท์พุท:

345
123

7
การสังเกตที่น่าสนใจ แต่ฉันคิดว่าคุณกำลังเดินผิดทาง ด้วยการพิมพ์ MyClass.i ดูเหมือนว่าคุณกำลังเรียกตัวแปร 'แบบคงที่' คุณกำลังเรียกตัวแปรสมาชิกอยู่ที่ไหนเช่นเดียวกับไอ สำหรับฉันแล้วinitนั้นเป็นเพียงตัวสร้างที่ถูกเรียกใช้ครั้งแรกเมื่อคุณสร้างวัตถุของคลาส
กัปตันที่

34
นั่นคือสิ่งที่ฉันพยายามที่จะ 'อธิบายกับตัวเอง' กับตัวอย่างนี้ - ตัวแปรที่กำหนดโดย__init__คือสิ่งที่ได้รับการส่งผ่านไปยังอินสแตนซ์ของชั้นเรียนไม่ใช่ตัวแปร 'คงที่' ของชั้นเรียนที่มีชื่อเดียวกัน ...
เดฟ Everitt

44

ในระยะสั้น:

  1. selfตามที่แนะนำหมายถึงตัวเอง - วัตถุที่เรียกว่าวิธีการ นั่นคือถ้าคุณมีวัตถุ N เรียกวิธีการนั้นself.aจะอ้างถึงอินสแตนซ์ที่แยกจากกันของตัวแปรสำหรับแต่ละวัตถุ N ลองนึกภาพสำเนาของตัวแปร Naสำหรับแต่ละวัตถุ
  2. __init__เป็นสิ่งที่เรียกว่าเป็นตัวสร้างในภาษา OOP อื่น ๆ เช่น C ++ / Java แนวคิดพื้นฐานคือมันเป็นวิธีพิเศษซึ่งจะถูกเรียกโดยอัตโนมัติเมื่อวัตถุของ Class นั้นถูกสร้างขึ้น

29

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


1
'ตัวเอง' กำหนดว่าวิธีการคงที่หรือไม่! ว้าวนั่นเป็นเครื่องเปิดตาสำหรับผู้ชายจาวานี้
liwevire

25

ลองใช้รหัสนี้ หวังว่ามันจะช่วยโปรแกรมเมอร์ C หลายคนอย่างผมเรียน Learn Py

#! /usr/bin/python2

class Person:

    '''Doc - Inside Class '''

    def __init__(self, name):
        '''Doc - __init__ Constructor'''
        self.n_name = name        

    def show(self, n1, n2):
        '''Doc - Inside Show'''
        print self.n_name
        print 'Sum = ', (n1 + n2)

    def __del__(self):
        print 'Destructor Deleting object - ', self.n_name

p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__

เอาท์พุท:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay


ฉันไม่รู้ว่ามันเป็นแค่ฉันหรือเปล่า แต่การอ่านรหัสนี้ค่อนข้างสับสนเล็กน้อย อาจเป็นเพราะฉันยังเป็นนักเขียนโปรแกรม Python มือใหม่ idk
Linny

ฉันไม่ชัดเจนเกี่ยวกับสิ่งdoc .. มันดึงเอกสารหรือไม่ และถ้าฉัน: '' 'ทดสอบ - เอกสารของฉัน' '' ฉันสามารถใช้: print.p .__ test__ ได้ไหม หรือ doc เป็นคำหลักเฉพาะ
โทมัส

@Thomas docเป็นคำหลักสำหรับรายละเอียดที่ทำเป็นเอกสาร การเสนอราคาแบบสามครั้งใช้สำหรับการเขียนเอกสารและเอกสารเป็นนิติบุคคลที่เป็นตัวเลือก
Jayzcode

24

อ็อบเจ็กต์คลาสสนับสนุนการดำเนินการสองชนิด: การอ้างอิงแอ็ตทริบิวต์และการสร้างอินสแตนซ์

การอ้างอิงแอททริบิวใช้ไวยากรณ์มาตรฐานที่ใช้สำหรับการอ้างอิงแอททริบิวทั้งหมดใน Python: obj.name ชื่อแอตทริบิวต์ที่ถูกต้องคือชื่อทั้งหมดที่อยู่ในเนมสเปซของคลาสเมื่อสร้างคลาสอ็อบเจ็กต์ ดังนั้นถ้านิยามคลาสดูเหมือนว่านี้:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

จากนั้นMyClass.iและMyClass.fเป็นการอ้างอิงแอตทริบิวต์ที่ถูกต้องส่งคืนจำนวนเต็มและฟังก์ชันวัตถุตามลำดับ สามารถกำหนดแอตทริบิวต์คลาสได้ดังนั้นคุณสามารถเปลี่ยนค่าของการMyClass.iกำหนดได้ __doc__ยังเป็นแอตทริบิวต์ที่ถูกต้องส่งคืน docstring ที่เป็นของคลาส: "คลาสตัวอย่างง่าย ๆ "

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

x = MyClass()

การดำเนินการสร้างอินสแตนซ์ (“ เรียก” วัตถุคลาส) สร้างวัตถุว่าง คลาสจำนวนมากต้องการสร้างวัตถุที่มีอินสแตนซ์ที่กำหนดให้เป็นสถานะเริ่มต้นที่เฉพาะเจาะจง ดังนั้นคลาสอาจกำหนดวิธีพิเศษที่ชื่อ__init__()เช่นนี้

def __init__(self):
    self.data = []

เมื่อคลาสกำหนด__init__()เมธอดการสร้างคลาสอินสแตนซ์จะเรียกใช้__init__()อินสแตนซ์คลาสที่สร้างขึ้นใหม่โดยอัตโนมัติ ดังนั้นในตัวอย่างนี้สามารถรับอินสแตนซ์ใหม่ได้โดย:

x = MyClass()

แน่นอน__init__()วิธีการอาจมีข้อโต้แย้งเพื่อความยืดหยุ่นมากขึ้น ในกรณีที่มีปากเสียงมอบให้กับผู้ประกอบการระดับ instantiation __init__()จะถูกส่งผ่านไปยัง ตัวอย่างเช่น,

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i

นำมาจากเอกสารอย่างเป็นทางการซึ่งช่วยฉันได้มากที่สุดในที่สุด


นี่คือตัวอย่างของฉัน

class Bill():
    def __init__(self,apples,figs,dates):
        self.apples = apples
        self.figs = figs
        self.dates = dates
        self.bill = apples + figs + dates
        print ("Buy",self.apples,"apples", self.figs,"figs 
                and",self.dates,"dates. 
                Total fruitty bill is",self.bill," pieces of fruit :)")

เมื่อคุณสร้างอินสแตนซ์ของคลาสบิล:

purchase = Bill(5,6,7)

คุณได้รับ:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)

22

มีปัญหาในการแก้ปัญหานี้ด้วยตนเอง แม้หลังจากอ่านคำตอบที่นี่

เพื่อให้เข้าใจ__init__วิธีการที่ถูกต้องคุณต้องเข้าใจตนเอง

พารามิเตอร์ตัวเอง

อาร์กิวเมนต์ที่ยอมรับโดย__init__เมธอดคือ:

def __init__(self, arg1, arg2):

แต่จริงๆแล้วเราผ่านมันไปสองข้อโต้แย้งเท่านั้น:

instance = OurClass('arg1', 'arg2')

ข้อโต้แย้งพิเศษมาจากไหน?

เมื่อเราเข้าถึงคุณลักษณะของวัตถุเราทำได้โดยใช้ชื่อ (หรือโดยการอ้างอิง) ตัวอย่างนี่คือการอ้างอิงถึงวัตถุใหม่ของเรา เราเข้าถึงวิธีการพิมพ์ของวัตถุตัวอย่างโดยใช้ instance.printargs

ในการเข้าถึงคุณสมบัติของวัตถุจากภายใน__init__วิธีการที่เราจำเป็นต้องมีการอ้างอิงไปยังวัตถุ

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

ซึ่งหมายความว่าใน__init__วิธีที่เราสามารถทำได้:

self.arg1 = arg1
self.arg2 = arg2

ที่นี่เรากำลังตั้งค่าคุณลักษณะบนวัตถุ คุณสามารถตรวจสอบได้โดยทำสิ่งต่อไปนี้:

instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1

ค่าเช่นนี้เรียกว่าแอตทริบิวต์ของวัตถุ นี่คือ__init__วิธีการตั้งค่าแอตทริบิวต์ arg1 และ arg2 ของอินสแตนซ์

แหล่งที่มา: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method


17

โปรดทราบว่าselfจริง ๆ แล้วอาจเป็นตัวระบุหลามที่ถูกต้อง ตัวอย่างเช่นเราสามารถเขียนได้อย่างง่ายดายจากตัวอย่างของ Chris B:

class A(object):
    def __init__(foo):
        foo.x = 'Hello'

    def method_a(bar, foo):
        print bar.x + ' ' + foo

และมันจะทำงานเหมือนกันทุกประการ อย่างไรก็ตามขอแนะนำให้ใช้ตัวเองเพราะงูใหญ่ตัวอื่นจะจดจำได้ง่ายกว่า


ฉันยอมรับว่าตัวเองจะได้รับการแนะนำแทน foo ช่วยโปรแกรมเมอร์คนอื่น ๆ ในการดูโค้ด
Linny

15

โดยทั่วไปคุณต้องใช้คำหลัก 'ตัวเอง' เมื่อใช้ตัวแปรในหลายฟังก์ชั่นภายในชั้นเดียวกัน สำหรับinitมันใช้เพื่อตั้งค่าเริ่มต้นเนื่องจากไม่มีฟังก์ชั่นอื่น ๆ จากภายในคลาสนั้น


6
ไม่มีคำหลัก 'ตัวเอง' ใน Python การเรียกพารามิเตอร์ตัวแรกว่า 'ตัวเอง' เป็นเพียงการประชุม
David Anderson

ตัวเองถูกใช้เป็นตัวยึดตำแหน่งโดยทั่วไป มันไม่จำเป็นต้องให้คุณใช้ตัวเองคุณสามารถใช้ "EEEE" หรือ "ฟู" หรืออย่างอื่นก็ขอแนะนำเพียงสำหรับการเขียนโปรแกรมอื่น ๆ ในขณะที่อ่านรหัสของคุณ
Linny

15
  1. __init__เป็นฟังก์ชั่นซึ่งจะ"เริ่มต้น" / "เปิดใช้งาน"คุณสมบัติของคลาสสำหรับวัตถุที่เฉพาะเจาะจงเมื่อสร้างและจับคู่กับคลาสที่สอดคล้องกัน ..
  2. self แสดงถึงวัตถุนั้นซึ่งจะสืบทอดคุณสมบัติเหล่านั้น

1
ไม่จำเป็นต้องใช้คำหลัก "ตัวเอง" เป็นเพียงตัวยึดตำแหน่ง คุณสามารถใช้คำใดก็ได้ แต่ขอแนะนำให้คุณใช้ตัวเองเพื่อช่วยให้โปรแกรมอ่านได้ง่ายขึ้น
Linny

13

'ตนเอง' เป็นการอ้างอิงถึงอินสแตนซ์ของคลาส

class foo:
    def bar(self):
            print "hi"

ตอนนี้เราสามารถสร้างอินสแตนซ์ของ foo และเรียกใช้เมธอดนั้นได้พารามิเตอร์ของตนเองถูกเพิ่มโดย Python ในกรณีนี้:

f = foo()
f.bar()

แต่สามารถส่งผ่านได้เช่นกันหากการเรียกใช้เมธอดไม่ได้อยู่ในบริบทของอินสแตนซ์ของคลาสรหัสด้านล่างทำสิ่งเดียวกัน

f = foo()
foo.bar(f)

น่าสนใจชื่อตัวแปร 'ตัวเอง' เป็นเพียงการประชุม คำจำกัดความด้านล่างจะทำงานเหมือนเดิม .. ต้องบอกว่ามันเป็นแบบแผนที่แข็งแกร่งมากซึ่งควรปฏิบัติตามเสมอแต่มันพูดอะไรบางอย่างเกี่ยวกับลักษณะที่ยืดหยุ่นของภาษา

class foo:
    def bar(s):
            print "hi"

ทำไมจึงพูดอะไรเกี่ยวกับลักษณะที่ยืดหยุ่นของภาษา มันเพิ่งบอกว่าคุณสามารถตั้งชื่อตัวแปรตามกฎหมายที่คุณเลือกได้ มันแตกต่างจากภาษาการเขียนโปรแกรมอื่น ๆ อย่างไร?
Daniel

ดังที่ฉันเขียนไว้ในคำตอบ "bar" เป็นเพียงฟังก์ชั่นที่มีอินสแตนซ์ของคลาสให้ไว้เป็นพารามิเตอร์แรก ดังนั้นในขณะที่ "บาร์" ถูกกำหนดให้เป็นวิธีการผูกกับ "foo" มันอาจถูกเรียกด้วยตัวอย่างของคลาสอื่น ๆ นี่ไม่ใช่วิธีการและ "นี่" ทำงานใน Java เช่นแม้ว่าฉันคิดว่าคุณเห็นว่าสิ่งเหล่านี้เป็นแนวคิดเดียวกันฟังก์ชั่นและบริบทอินสแตนซ์บางอย่าง (บริบทอินสแตนซ์เป็นพารามิเตอร์แรกใน Python และ "this" ใน Java ") บางทีตอนนี้คุณสามารถเห็นความยืดหยุ่นของภาษาที่ฉันพูดถึงได้ไหม
tarn

ใช่นั่นแสดงให้เห็นถึงความยืดหยุ่นของภาษา วิธีที่คุณใช้คำตอบของคุณดูเหมือนคุณกำลังบอกว่าความจริงที่ว่าคุณสามารถเรียกตัวแปร "ตัวเอง" อย่างอื่น (เช่นs) แสดงความยืดหยุ่นของงูหลาม
Daniel

12

เป็นเพียงตัวอย่างสำหรับคำถาม

class MyClass:

    def __init__(self):
        print('__init__ is the constructor for a class')

    def __del__(self):
        print('__del__ is the destructor for a class')

    def __enter__(self):
        print('__enter__ is for context manager')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__ is for context manager')

    def greeting(self):
        print('hello python')


if __name__ == '__main__':
    with MyClass() as mycls:
        mycls.greeting()

$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class

11

ในรหัสนี้:

class Cat:
    def __init__(self, name):
        self.name = name
    def info(self):
        print 'I am a cat and I am called', self.name

ที่นี่__init__ทำหน้าที่เป็นตัวสร้างสำหรับคลาสและเมื่อวัตถุถูกสร้างอินสแตนซ์ฟังก์ชันนี้จะถูกเรียก selfแสดงถึงวัตถุ instantiating

c = Cat('Kitty')
c.info()

ผลลัพธ์ของข้อความข้างต้นจะเป็นดังนี้:

I am a cat and I am called Kitty

11

อะไรตัวเองทำอย่างไร มันหมายความว่าอะไร มันคือการบังคับ ?

อาร์กิวเมนต์แรกของวิธีการเรียนทุกครั้งรวมถึง init จะอ้างอิงถึงอินสแตนซ์ปัจจุบันของคลาสเสมอ selfโดยการประชุมเรื่องนี้เป็นชื่อเสมอ ในวิธีการเริ่มต้นselfหมายถึงวัตถุที่สร้างขึ้นใหม่ ในวิธีการเรียนอื่น ๆ มันหมายถึงอินสแตนซ์ที่มีวิธีการที่ถูกเรียก

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

TypeError: __init___() takes no arguments (1 given)

อะไรinitวิธีการทำอย่างไร ทำไมถึงจำเป็น? (อื่น ๆ )

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


8
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

class MyClass(object):
    # class variable
    my_CLS_var = 10

    # sets "init'ial" state to objects/instances, use self argument
    def __init__(self):
        # self usage => instance variable (per object)
        self.my_OBJ_var = 15

        # also possible, class name is used => init class variable
        MyClass.my_CLS_var = 20


def run_example_func():
    # PRINTS    10    (class variable)
    print MyClass.my_CLS_var

    # executes __init__ for obj1 instance
    # NOTE: __init__ changes class variable above
    obj1 = MyClass()

    # PRINTS    15    (instance variable)
    print obj1.my_OBJ_var

    # PRINTS    20    (class variable, changed value)
    print MyClass.my_CLS_var


run_example_func()

5

งูหลาม__init__และselfพวกเขาจะทำอย่างไร

อะไร selfทำอย่างไร มันหมายความว่าอะไร จำเป็นหรือไม่

อะไร__init__วิธีการทำอย่างไร ทำไมถึงจำเป็น? (อื่น ๆ )

ตัวอย่างที่ให้มานั้นไม่ถูกต้องดังนั้นให้ฉันสร้างตัวอย่างที่ถูกต้องตามนั้น:

class SomeObject(object):

    def __init__(self, blah):
        self.blah = blah

    def method(self):
        return self.blah 

เมื่อเราสร้างอินสแตนซ์ของวัตถุ__init__จะถูกเรียกให้ปรับแต่งวัตถุหลังจากที่มันถูกสร้างขึ้น นั่นคือเมื่อเราเรียกSomeObjectกับ'blah'ด้านล่าง (ซึ่งอาจจะเป็นอะไร) จะได้รับการส่งผ่านไปยัง__init__ฟังก์ชั่นเป็นอาร์กิวเมนต์ที่blah:

an_object = SomeObject('blah')

selfอาร์กิวเมนต์เป็นตัวอย่างของSomeObjectที่จะได้รับมอบหมายให้an_objectที่จะได้รับมอบหมายให้

ต่อมาเราอาจต้องการเรียกวิธีการในวัตถุนี้:

an_object.method()

การค้นหาจุดประคือ an_object.methodผูกอินสแตนซ์ของอินสแตนซ์ของฟังก์ชันและวิธีการ (ตามที่เรียกข้างต้น) ตอนนี้เป็นวิธี "ผูก" - ซึ่งหมายความว่าเราไม่จำเป็นต้องส่งตัวอย่างไปยังวิธีการโทรอย่างชัดเจน .

การเรียกเมธอดได้รับอินสแตนซ์เนื่องจากถูกผูกไว้กับการค้นหาจุดและเมื่อเรียกใช้จากนั้นเรียกใช้งานโค้ดใด ๆ

selfอาร์กิวเมนต์ที่ส่งผ่านโดยนัยถูกเรียกใช้selfโดยการประชุม เราสามารถใช้ชื่อ Python ตามกฎหมายอื่น ๆ ได้ แต่คุณอาจจะได้รับ tarred และขนนกโดยโปรแกรมเมอร์ Python อื่น ๆ หากคุณเปลี่ยนเป็นอย่างอื่น

__init__เป็นวิธีพิเศษการบันทึกไว้ในเอกสาร DataModel หลาม มันถูกเรียกทันทีหลังจากอินสแตนซ์ถูกสร้างขึ้น (โดยทั่วไปผ่าน__new__- แม้ว่า__new__จะไม่จำเป็นเว้นแต่คุณจะ subclassing ประเภทข้อมูลที่ไม่เปลี่ยนรูป)


3

ที่นี่คนเขียนค่อนข้างดีและเรียบง่าย: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-cython-classes-and-object-oriented-programming/

อ่านลิงก์ด้านบนเป็นการอ้างอิงถึงสิ่งนี้:

self? ดังนั้นสิ่งที่มีพารามิเตอร์ตัวเองเพื่อทุกวิธีของลูกค้า? มันคืออะไร? ทำไมมันถึงเป็นตัวอย่างแน่นอน! อีกวิธีหนึ่งเช่นวิธีการถอนกำหนดคำแนะนำสำหรับการถอนเงินจากบัญชีของลูกค้าที่เป็นนามธรรม การโทร jeff.withdraw (100.0) ทำให้คำแนะนำเหล่านั้นใช้กับอินสแตนซ์ของ jeff

ดังนั้นเมื่อเราพูด def def (ตัวเองจำนวน): เรากำลังพูดว่า "นี่คือวิธีที่คุณถอนเงินจากวัตถุลูกค้า (ซึ่งเราจะเรียกตนเอง) และตัวเลขดอลลาร์ (ซึ่งเราจะเรียกจำนวนเงิน) เป็นอินสแตนซ์ของลูกค้าที่กำลังถูกถอนการเรียกนั่นไม่ใช่ฉันกำลังทำการเปรียบเทียบด้วยเช่นกัน jeff.withdraw (100.0) เป็นเพียงชวเลขสำหรับลูกค้าที่ถอนออก (jeff, 100.0) ซึ่งใช้ได้อย่างสมบูรณ์ รหัส.

ตนเองinitอาจเข้าท่ากับวิธีอื่น ๆ แต่แล้วinitล่ะ? เมื่อเราเรียกinitเรากำลังอยู่ในขั้นตอนการสร้างวัตถุดังนั้นจะมีตัวเองได้อย่างไร Python ช่วยให้เราสามารถขยายรูปแบบของตัวเองเป็นเมื่อวัตถุถูกสร้างขึ้นเช่นกันแม้ว่ามันจะไม่พอดี แค่คิดว่า jeff = ลูกค้า ('Jeff Knupp', 1000.0) เหมือนกับการโทร jeff = ลูกค้า (jeff, 'Jeff Knupp', 1000.0); jeff ที่ผ่านเข้าไปนั้นก็ทำผลลัพธ์เช่นกัน

นี่คือเหตุผลที่เมื่อเราเรียกinitเราจะเริ่มต้นวัตถุโดยพูดสิ่งต่าง ๆ เช่น self.name = name โปรดจำไว้ว่าเนื่องจากตัวเองเป็นตัวอย่างสิ่งนี้จึงเทียบเท่ากับการพูด jeff.name = name ซึ่งเหมือนกับ jeff.name = 'Jeff Knupp ในทำนองเดียวกัน self.balance = balance จะเหมือนกับ jeff.balance = 1000.0 หลังจากสองบรรทัดนี้เราจะพิจารณาออบเจ็กต์ลูกค้า "กำหนดค่าเริ่มต้น" และพร้อมใช้งาน

ระวังสิ่งที่คุณ __init__

หลังจากinitเสร็จสิ้นแล้วผู้เรียกสามารถสันนิษฐานได้ว่าวัตถุพร้อมใช้งานอย่างถูกต้อง นั่นคือหลังจาก jeff = ลูกค้า ('Jeff Knupp', 1,000.0) เราสามารถเริ่มต้นการฝากและถอนสายบน jeff; เจฟฟ์เป็นวัตถุที่เริ่มต้นอย่างเต็มที่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.