เหตุใดเราจึงใช้ __init__ ในคลาส Python


124

ฉันมีปัญหาในการทำความเข้าใจเกี่ยวกับการเริ่มต้นคลาส

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

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

class crawler:
  # Initialize the crawler with the name of database
  def __init__(self,dbname):
    self.con=sqlite.connect(dbname)

  def __del__(self):
    self.con.close()

  def dbcommit(self):
    self.con.commit()

หรือตัวอย่างโค้ดอื่น:

class bicluster:
  def __init__(self,vec,left=None,right=None,distance=0.0,id=None):
    self.left=left
    self.right=right
    self.vec=vec
    self.id=id
    self.distance=distance

มีคลาสมากมายที่__init__ฉันเจอเมื่อพยายามอ่านรหัสของคนอื่น แต่ฉันไม่เข้าใจตรรกะในการสร้าง


1
เรื่องราวของinitคือ ... blah, blah, blah .... constructor-destructor แต่ไม่มีตัวทำลายเพราะมีการรวบรวมขยะ
MisterGeeky

คำตอบ:


289

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

เมื่อคุณพูดว่า

class Dog:
    def __init__(self, legs, colour):
        self.legs = legs
        self.colour = colour

fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")

คุณกำลังพูดว่า Fido เป็นสุนัขสีน้ำตาลที่มี 4 ขาในขณะที่ Spot เป็นคนพิการเล็กน้อยและส่วนใหญ่เป็นสีเหลือง __init__ฟังก์ชั่นที่เรียกว่าคอนสตรัคหรือการเริ่มต้นและมีการเรียกโดยอัตโนมัติเมื่อคุณสร้างตัวอย่างใหม่ของชั้นเรียน selfภายในฟังก์ชันที่วัตถุที่สร้างขึ้นใหม่ได้รับมอบหมายให้พารามิเตอร์ สัญกรณ์self.legsเป็นคุณลักษณะที่เรียกว่าของวัตถุในตัวแปรlegs selfแอตทริบิวต์เป็นเหมือนตัวแปร แต่อธิบายสถานะของวัตถุหรือการกระทำ (ฟังก์ชัน) ที่มีให้กับวัตถุ

อย่างไรก็ตามโปรดสังเกตว่าคุณไม่ได้ตั้งเป้าหมายไว้ที่colourความมุ่งมั่น แต่เป็นแนวคิดนามธรรม มีคุณลักษณะที่เหมาะสมกับชั้นเรียน ตัวอย่างpopulation_sizeเช่นมันไม่สมเหตุสมผลที่จะนับ Fido เพราะ Fido เป็นหนึ่งเสมอ การนับสุนัขเป็นเรื่องที่สมเหตุสมผล สมมติว่ามีสุนัข 200 ล้านตัวในโลก เป็นสมบัติของคลาส Dog Fido ไม่มีส่วนเกี่ยวข้องกับจำนวน 200 ล้านหรือ Spot มันเรียกว่า "ชั้นแอตทริบิวต์" เมื่อเทียบกับ "คุณลักษณะเช่น" ที่มีcolourหรือlegsข้างต้น

ตอนนี้เป็นสิ่งที่สุนัขน้อยและเกี่ยวข้องกับการเขียนโปรแกรมมากขึ้น ตามที่ฉันเขียนไว้ด้านล่างคลาสเพื่อเพิ่มสิ่งต่างๆไม่สมเหตุสมผล - คลาสของอะไร? คลาสใน Python ประกอบด้วยคอลเล็กชันของข้อมูลที่แตกต่างกันซึ่งทำงานในลักษณะเดียวกัน ประเภทของสุนัขประกอบด้วย Fido และ Spot และ 199999999998 สัตว์อื่น ๆ ที่คล้ายกับพวกมันทุกตัวกำลังฉี่บนเสาไฟ คลาสสำหรับเพิ่มสิ่งต่างๆประกอบด้วยอะไรบ้าง? ข้อมูลที่มีอยู่ในตัวพวกเขาแตกต่างกันอย่างไร? และพวกเขาแบ่งปันการกระทำอะไรบ้าง?

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

ดังนั้นจำนวนเต็มจึงเป็นคลาส พวกเขามีข้อมูลบางอย่าง (ค่า) และพฤติกรรมบางอย่าง ("เพิ่มฉันในหมายเลขอื่นนี้") มาแสดงสิ่งนี้:

class MyInteger:
    def __init__(self, newvalue)
        # imagine self as an index card.
        # under the heading of "value", we will write
        # the contents of the variable newvalue.
        self.value = newvalue
    def add(self, other):
        # when an integer wants to add itself to another integer,
        # we'll take their values and add them together,
        # then make a new integer with the result value.
        return MyInteger(self.value + other.value)

three = MyInteger(3)
# three now contains an object of class MyInteger
# three.value is now 3
five = MyInteger(5)
# five now contains an object of class MyInteger
# five.value is now 5
eight = three.add(five)
# here, we invoked the three's behaviour of adding another integer
# now, eight.value is three.value + five.value = 3 + 5 = 8
print eight.value
# ==> 8

นี่ค่อนข้างบอบบาง (เราสมมติว่าotherเป็น MyInteger) แต่ตอนนี้เราจะไม่สนใจ ในรหัสจริงเราจะไม่; เราจะทดสอบเพื่อให้แน่ใจและอาจจะบังคับด้วยซ้ำ ("คุณไม่ใช่จำนวนเต็มเหรอโดย golly คุณมี 10 นาโนวินาทีที่จะกลายเป็นหนึ่ง 9 ... 8 .... ")

เราสามารถกำหนดเศษส่วนได้ เศษส่วนยังรู้วิธีเพิ่มตัวเอง

class MyFraction:
    def __init__(self, newnumerator, newdenominator)
        self.numerator = newnumerator
        self.denominator = newdenominator
        # because every fraction is described by these two things
    def add(self, other):
        newdenominator = self.denominator * other.denominator
        newnumerator = self.numerator * other.denominator + self.denominator * other.numerator
        return MyFraction(newnumerator, newdenominator)

มีเศษส่วนมากกว่าจำนวนเต็ม (ไม่จริง แต่คอมพิวเตอร์ไม่รู้) ลองสร้างสอง:

half = MyFraction(1, 2)
third = MyFraction(1, 3)
five_sixths = half.add(third)
print five_sixths.numerator
# ==> 5
print five_sixths.denominator
# ==> 6

คุณไม่ได้ประกาศอะไรที่นี่ แอตทริบิวต์เปรียบเสมือนตัวแปรชนิดใหม่ ตัวแปรปกติมีเพียงค่าเดียว colour = "grey"ให้เราบอกคุณเขียน คุณไม่สามารถตั้งชื่อตัวแปรอื่นcolourที่เป็น"fuchsia"- ไม่ได้อยู่ในตำแหน่งเดียวกันในโค้ด

อาร์เรย์แก้ปัญหานั้นในระดับหนึ่ง ถ้าคุณบอกว่าcolour = ["grey", "fuchsia"]คุณได้ซ้อนสีสองสีไว้ในตัวแปร แต่คุณแยกความแตกต่างตามตำแหน่ง (0 หรือ 1 ในกรณีนี้)

แอตทริบิวต์คือตัวแปรที่ผูกไว้กับวัตถุ เช่นเดียวกับอาร์เรย์เราสามารถมีความอุดมสมบูรณ์colourตัวแปรในสุนัขที่แตกต่างกัน ดังนั้นfido.colourเป็นหนึ่งในตัวแปร แต่spot.colourเป็นอีกหนึ่ง คนแรกที่ถูกผูกไว้กับวัตถุที่อยู่ภายในตัวแปรfido; ที่สอง, spot. ตอนนี้เมื่อคุณเรียกDog(4, "brown")หรือthree.add(five)จะมีพารามิเตอร์ที่มองไม่เห็นอยู่เสมอซึ่งจะถูกกำหนดให้กับตัวห้อยพิเศษที่ด้านหน้าของรายการพารามิเตอร์ เรียกตามอัตภาพselfและจะได้รับค่าของวัตถุที่อยู่หน้าจุด ดังนั้นภายใน Dog's __init__(ผู้สร้าง) selfจะเป็นอะไรก็ตามที่สุนัขตัวใหม่จะกลายเป็น; ภายในMyInteger's add, จะถูกผูกไว้กับวัตถุในตัวแปรself threeดังนั้นthree.valueจะเป็นตัวแปรเดียวกับภายนอกaddเช่นเดียวกับself.valueภายในadd.

ถ้าฉันพูดthe_mangy_one = fidoฉันจะเริ่มอ้างถึงวัตถุที่รู้จักกันในfidoชื่ออื่น จากนี้ไปfido.colourเป็นตัวแปรเดียวกับthe_mangy_one.colour.

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

ชัดเจนกว่านี้ไหม

แก้ไข : ขยายความคิดเห็นด้านล่าง:

คุณหมายถึงรายการวัตถุใช่ไหม

ประการแรกfidoไม่ใช่วัตถุ มันเป็นตัวแปรซึ่งขณะนี้มีวัตถุเช่นเดียวกับเมื่อคุณพูดx = 5, xเป็นตัวแปรในปัจจุบันมีจำนวนห้า หากคุณเปลี่ยนใจในภายหลังคุณสามารถทำได้fido = Cat(4, "pleasing")(ตราบเท่าที่คุณสร้างคลาสCat) และfidoจากนั้นจะ "มี" วัตถุที่เป็นแมว ถ้าคุณทำfido = xมันจะมีตัวเลขห้าไม่ใช่สัตว์เลย

คลาสโดยตัวมันเองจะไม่รู้จักอินสแตนซ์ของมันเว้นแต่คุณจะเขียนโค้ดเพื่อติดตามมันโดยเฉพาะ ตัวอย่างเช่น:

class Cat:
    census = [] #define census array

    def __init__(self, legs, colour):
        self.colour = colour
        self.legs = legs
        Cat.census.append(self)

นี่censusคือแอตทริบิวต์Catระดับชั้นของคลาส

fluffy = Cat(4, "white")
spark = Cat(4, "fiery")
Cat.census
# ==> [<__main__.Cat instance at 0x108982cb0>, <__main__.Cat instance at 0x108982e18>]
# or something like that

[fluffy, sparky]โปรดทราบว่าคุณจะไม่ได้รับ นี่เป็นเพียงชื่อตัวแปร หากคุณต้องการให้แมวมีชื่อคุณต้องสร้างแอตทริบิวต์แยกต่างหากสำหรับชื่อจากนั้นจึงแทนที่__str__เมธอดเพื่อส่งคืนชื่อนี้ วัตถุประสงค์ของเมธอดนี้ (เช่นฟังก์ชันที่มีขอบเขตคลาสเช่นเดียวกับaddหรือ__init__) คือการอธิบายวิธีการแปลงวัตถุเป็นสตริงเช่นเมื่อคุณพิมพ์ออกมา


7
ว้าวขอบคุณ.. สิ่งนี้ทำให้ฉันรู้สึกดีมากดังนั้นอะไรก็ตามที่ทำให้บางสิ่งบางอย่างมันคืออะไรฉันต้องประกาศล่วงหน้าในฟังก์ชัน init ในกรณีนี้สุนัขมีขาและสี ตัวอย่างเช่นถ้าฉันสร้างชั้นเรียนที่เพิ่มตัวเลขสองตัวฉันจะประกาศ self.firstnumber และ self.secondnumber จากนั้นทำ firstnumber + secondnumber ในภายหลังในคลาสเพื่อรับคำตอบ?
Lostsoul

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

3
ขอบคุณสำหรับคำตอบที่น่าทึ่ง ฉันเห็นและเข้าใจพลังของชั้นเรียนแล้ว ขออภัยถ้าฟังดูโง่ คุณเพียงแค่ฉันรู้ว่าฉันสามารถจัดเรียงข้อมูลและรักษาสถานะของสิ่งต่างๆได้หลายอย่างพร้อมกัน (ในขณะที่ฉันจะติดตามตัวแปรให้มากที่สุดเท่าที่ฉันจะสร้างได้หรือมากกว่านั้นผ่านลูป) สมมติว่าฉันต้องหาจำนวนขาเฉลี่ยต่อสุนัขหรือไม่? มีวิธีดึงรายการวัตถุทั้งหมดที่ฉันสร้างด้วยคลาสเพื่อให้ฉันสามารถเริ่มการคำนวณแบบนี้ได้หรือไม่? หรือฉันควรจะรักษารายชื่อคลาสที่ฉันสร้างไว้ (เช่น [fido, spot])
Lostsoul

23

การมีส่วนร่วม 5 เซนต์ของฉันไปที่คำอธิบายอย่างละเอียดจาก Amadan

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

  1. การห่อหุ้ม (จะไม่อธิบายรายละเอียดในเรื่องนี้)
  2. มรดก
  3. ความแตกต่าง

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

    class Human:
        gender
        nationality
        favorite_drink
        core_characteristic
        favorite_beverage
        name
        age

        def love    
        def drink
        def laugh
        def do_your_special_thing                

    class Americans(Humans)
        def drink(beverage):
            if beverage != favorite_drink: print "You call that a drink?"
            else: print "Great!" 

    class French(Humans)
        def drink(beverage, cheese):
            if beverage == favourite_drink and cheese == None: print "No cheese?" 
            elif beverage != favourite_drink and cheese == None: print "Révolution!"

    class Brazilian(Humans)
        def do_your_special_thing
            win_every_football_world_cup()

    class Germans(Humans)
        def drink(beverage):
            if favorite_drink != beverage: print "I need more beer"
            else: print "Lecker!" 

    class HighSchoolStudent(Americans):
        def __init__(self, name, age):
             self.name = name
             self.age = age

jeff = HighSchoolStudent(name, age):
hans = Germans()
ronaldo = Brazilian()
amelie = French()

for friends in [jeff, hans, ronaldo]:
    friends.laugh()
    friends.drink("cola")
    friends.do_your_special_thing()

print amelie.love(jeff)
>>> True
print ronaldo.love(hans)
>>> False

ลักษณะบางอย่างกำหนดมนุษย์ แต่ทุกสัญชาติมีความแตกต่างกันบ้าง ดังนั้น "ชาติประเภท" จึงเป็นมนุษย์ที่มีความพิเศษ "ชาวอเมริกัน" เป็น "มนุษย์" ประเภทหนึ่งและสืบทอดลักษณะและพฤติกรรมที่เป็นนามธรรมบางอย่างจากประเภทของมนุษย์ (ระดับฐาน) นั่นคือการถ่ายทอดทางพันธุกรรม ดังนั้นมนุษย์ทุกคนสามารถหัวเราะและดื่มได้ดังนั้นเด็กทุกคนก็สามารถทำได้เช่นกัน! มรดก (2).

แต่เนื่องจากเป็นประเภทเดียวกันทั้งหมด (Type / base-class: Humans) คุณสามารถแลกเปลี่ยนได้บางครั้ง: ดู for-loop ในตอนท้าย แต่พวกเขาจะเปิดเผยลักษณะเฉพาะของแต่ละบุคคลและนั่นคือ Polymorphism (3)

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

hans = German(favorite_drink = "Cola")

สร้างอินสแตนซ์คลาสเยอรมันและฉัน "เปลี่ยน" คุณสมบัติเริ่มต้นเมื่อเริ่มต้น (แต่ถ้าคุณเรียก hans.drink ('นม') เขาจะยังคงพิมพ์ว่า "ฉันต้องการเบียร์มากกว่านี้" ซึ่งเป็นข้อผิดพลาดที่ชัดเจน ... หรือนั่นอาจเป็นสิ่งที่ฉันจะเรียกว่าคุณลักษณะถ้าฉันจะเป็นพนักงานของ บริษัท ที่ใหญ่กว่า ;-)! )

ลักษณะเฉพาะของประเภทเช่นเยอรมัน (ฮันส์) มักถูกกำหนดผ่านตัวสร้าง (ใน python :) __init__ในช่วงเวลาของการสร้างอินสแตนซ์ นี่คือจุดที่คุณกำหนดคลาสให้กลายเป็นวัตถุ คุณสามารถพูดชีวิตลมหายใจให้เป็นแนวคิดนามธรรม (ชั้นเรียน) โดยเติมเต็มด้วยลักษณะเฉพาะของแต่ละบุคคลและกลายเป็นวัตถุ

แต่เนื่องจากออบเจ็กต์ทุกชิ้นเป็นอินสแตนซ์ของคลาสพวกเขาจึงแบ่งปันลักษณะพื้นฐานบางประเภทและพฤติกรรมบางอย่าง นี่เป็นข้อได้เปรียบที่สำคัญของแนวคิดเชิงวัตถุ

เพื่อปกป้องลักษณะเฉพาะของแต่ละวัตถุที่คุณห่อหุ้มไว้ - หมายความว่าคุณพยายามจับคู่พฤติกรรมและลักษณะและทำให้ยากที่จะจัดการกับวัตถุจากภายนอกวัตถุ นั่นคือ Encapsulation (1)


5

เป็นเพียงการเริ่มต้นตัวแปรของอินสแตนซ์

เช่นสร้างcrawlerอินสแตนซ์ที่มีชื่อฐานข้อมูลเฉพาะ (จากตัวอย่างของคุณด้านบน)


ขอโทษค่ะฉันไม่เข้าใจจริงๆว่ามันหมายถึงอะไร .. ในตัวอย่างข้างบนนี้ .. ผู้พัฒนาเพิ่งเพิ่มโค้ดหลัก 'left = foo' ไว้ในโค้ดหลักไม่ได้หรือ
เปล่า

คุณหมายถึงค่าเริ่มต้นของฟังก์ชัน? left=Noneleft จะเริ่มต้นเป็นNoneif เมื่อสร้างleftพารามิเตอร์ไม่ได้ระบุ
jldupont

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

1
@Lostsoul: left = fooจะทำงาน - ครั้งเดียว ประเด็นของชั้นเรียนคือการทำสิ่งที่สมเหตุสมผลสำหรับทุกคนที่แตกต่างกันcrawlerจุดของการเรียนคือการทำบางสิ่งบางอย่างที่เหมาะสมสำหรับทุกคนที่แตกต่างกันคลาสไม่ใช่ฟังก์ชันหรือสิ่งที่สามารถเปรียบเทียบกับฟังก์ชันได้ (ไม่ใช่จนกว่าคุณจะก้าวหน้าขึ้นมากและเข้าสู่การเขียนโปรแกรมเชิงฟังก์ชัน แต่นั่นจะทำให้คุณสับสนในตอนนี้) อ่านคำตอบของฉันว่าชั้นเรียนเป็นอย่างไร - คุณยังไม่เข้าใจ
Amadan

4

ดูเหมือนว่าคุณต้องใช้__init__ใน Python หากคุณต้องการเริ่มต้นแอตทริบิวต์ที่เปลี่ยนแปลงได้ของอินสแตนซ์ของคุณอย่างถูกต้อง

ดูตัวอย่างต่อไปนี้:

>>> class EvilTest(object):
...     attr = []
... 
>>> evil_test1 = EvilTest()
>>> evil_test2 = EvilTest()
>>> evil_test1.attr.append('strange')
>>> 
>>> print "This is evil:", evil_test1.attr, evil_test2.attr
This is evil: ['strange'] ['strange']
>>> 
>>> 
>>> class GoodTest(object):
...     def __init__(self):
...         self.attr = []
... 
>>> good_test1 = GoodTest()
>>> good_test2 = GoodTest()
>>> good_test1.attr.append('strange')
>>> 
>>> print "This is good:", good_test1.attr, good_test2.attr
This is good: ['strange'] []

สิ่งนี้แตกต่างกันมากใน Java โดยที่แต่ละแอตทริบิวต์จะเริ่มต้นโดยอัตโนมัติด้วยค่าใหม่:

import java.util.ArrayList;
import java.lang.String;

class SimpleTest
{
    public ArrayList<String> attr = new ArrayList<String>();
}

class Main
{
    public static void main(String [] args)
    {
        SimpleTest t1 = new SimpleTest();
        SimpleTest t2 = new SimpleTest();

        t1.attr.add("strange");

        System.out.println(t1.attr + " " + t2.attr);
    }
}

สร้างผลลัพธ์ที่เราคาดหวังโดยสัญชาตญาณ:

[strange] []

แต่ถ้าคุณประกาศ attrเป็นstaticมันจะทำหน้าที่เหมือน Python:

[strange] [strange]

3

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

class Car:
    def __init__(self, color, brand, number_of_seats):
        self.color = color
        self.brand = brand
        self.number_of_seats = number_of_seats
        self.number_of_wheels = 4
        self.registration_number = GenerateRegistrationNumber()

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

my_car = Car('blue', 'Renault', 2)

ด้วยวิธีนี้เรากำลังสร้างอินสแตนซ์ของCarคลาส __init__เป็นหนึ่งที่มีการจัดการคุณลักษณะเฉพาะของเรา (เช่นcolorหรือbrand) และสร้างของคุณลักษณะอื่น ๆ registration_numberเช่น


3

คลาสคืออ็อบเจ็กต์ที่มีคุณลักษณะ (สถานะลักษณะเฉพาะ) และวิธีการ (ฟังก์ชันความจุ) ที่เฉพาะเจาะจงสำหรับวัตถุนั้น ๆ (เช่นสีขาวและพลังบินตามลำดับสำหรับเป็ด)

เมื่อคุณสร้างตัวอย่างของชั้นเรียนคุณสามารถกำหนดบุคลิกเริ่มต้นบางอย่าง (สถานะหรือลักษณะเช่นชื่อและสีชุดของเธอสำหรับทารกแรกเกิด) คุณทำสิ่งนี้กับ__init__.

โดยทั่วไปกำหนดลักษณะเช่นโดยอัตโนมัติเมื่อคุณเรียก__init__instance = MyClass(some_individual_traits)


2

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

mycluster = bicluster(...actual values go here...)
mycluster.left # returns the value passed in as 'left'

ตรวจสอบPython Docsสำหรับข้อมูลบางอย่าง คุณจะต้องเลือกหนังสือเกี่ยวกับแนวคิด OO เพื่อเรียนรู้ต่อไป


1
class Dog(object):

    # Class Object Attribute
    species = 'mammal'

    def __init__(self,breed,name):
        self.breed = breed
        self.name = name

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

class Dog(object):
    a = '12'

    def __init__(self,breed,name,a):
        self.breed = breed
        self.name = name
        self.a= a

หากคุณพิมพ์ตัวอย่างข้างต้นโดยเรียกด้านล่างเช่นนี้

Dog.a
12

Dog('Lab','Sam','10')
Dog.a
10

นั่นหมายความว่าจะเริ่มต้นระหว่างการสร้างวัตถุเท่านั้น ดังนั้นสิ่งใดก็ตามที่คุณต้องการประกาศเป็นค่าคงที่ให้เป็น global และสิ่งที่เปลี่ยนแปลงใช้ __init__

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