portaldacalheta.pt
  • หลัก
  • การจัดการวิศวกรรม
  • Kpi และ Analytics
  • เทคโนโลยี
  • ว่องไว
เทคโนโลยี

คุณสมบัติของคลาส Python: คำแนะนำที่ละเอียดเกินไป



ฉันมี สัมภาษณ์การเขียนโปรแกรม เมื่อเร็ว ๆ นี้หน้าจอโทรศัพท์ที่เราใช้ไฟล์ โปรแกรมแก้ไขข้อความที่ทำงานร่วมกัน .

ฉันถูกขอให้ใช้ API บางตัว และเลือกที่จะทำใน Python . สมมติว่าฉันต้องการคลาสที่มีอินสแตนซ์เก็บไว้บางส่วน data และบางส่วน other_data.



ฉันหายใจเข้าลึก ๆ และเริ่มพิมพ์ หลังจากผ่านไปสองสามบรรทัดฉันมีสิ่งนี้:



class Service(object): data = [] def __init__(self, other_data): self.other_data = other_data ...

ผู้สัมภาษณ์ของฉันหยุดฉัน:



  • ผู้สัมภาษณ์:“ บรรทัดนั้น: data = []. ฉันคิดว่านั่นคือ Python ที่ถูกต้องไม่ใช่เหรอ”
  • ฉัน:“ ฉันค่อนข้างมั่นใจว่าเป็นอย่างนั้น เป็นเพียงการตั้งค่าเริ่มต้นสำหรับแอตทริบิวต์อินสแตนซ์”
  • ผู้สัมภาษณ์:“ รหัสนั้นจะถูกเรียกใช้งานเมื่อใด”
  • ฉัน:“ ฉันไม่แน่ใจจริงๆ ฉันจะแก้ไขเพื่อไม่ให้เกิดความสับสน”

สำหรับการอ้างอิงและเพื่อให้คุณทราบว่าฉันกำลังจะไปเพื่ออะไรนี่คือวิธีที่ฉันแก้ไขโค้ด:

หนี้แปลงสภาพเทียบกับตราสารทุนที่แปลงสภาพได้
class Service(object): def __init__(self, other_data): self.data = [] self.other_data = other_data ...

ปรากฎว่าเราผิดทั้งคู่ คำตอบที่แท้จริงคือการทำความเข้าใจความแตกต่างระหว่างแอตทริบิวต์คลาส Python และแอตทริบิวต์อินสแตนซ์ Python



แอตทริบิวต์คลาส Python เทียบกับแอตทริบิวต์อินสแตนซ์ Python

หมายเหตุ: หากคุณมีผู้เชี่ยวชาญในการจัดการแอตทริบิวต์คลาสคุณสามารถข้ามไปที่ กรณีการใช้งาน .



คุณสมบัติของคลาส Python

ผู้สัมภาษณ์ของฉันผิดรหัสข้างต้น คือ ถูกต้องตามหลักไวยากรณ์

ฉันคิดผิดเช่นกันที่ไม่ได้ตั้งค่า 'ค่าเริ่มต้น' สำหรับแอตทริบิวต์อินสแตนซ์ แต่เป็นการกำหนด data เป็น ชั้นเรียน แอตทริบิวต์ที่มีค่า [].



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

Python Class Variable vs. Instance Variable: อะไรคือความแตกต่าง?

แอตทริบิวต์คลาส Python เป็นแอตทริบิวต์ของคลาส (ฉันรู้แบบวงกลม) แทนที่จะเป็นแอตทริบิวต์ของไฟล์ ตัวอย่าง ของชั้นเรียน



ลองใช้ตัวอย่างคลาส Python เพื่อแสดงความแตกต่าง ที่นี่ class_var เป็นแอตทริบิวต์คลาสและ i_var เป็นแอตทริบิวต์อินสแตนซ์:

class MyClass(object): class_var = 1 def __init__(self, i_var): self.i_var = i_var

โปรดทราบว่าอินสแตนซ์ทั้งหมดของคลาสสามารถเข้าถึง class_var ได้และยังสามารถเข้าถึงได้ในฐานะคุณสมบัติของ คลาสนั่นเอง :



foo = MyClass(2) bar = MyClass(3) foo.class_var, foo.i_var ## 1, 2 bar.class_var, bar.i_var ## 1, 3 MyClass.class_var ## <— This is key ## 1

สำหรับโปรแกรมเมอร์ Java หรือ C ++ แอตทริบิวต์คลาสจะคล้ายกัน แต่ไม่เหมือนกันกับสมาชิกแบบคงที่ เราจะมาดูความแตกต่างในภายหลัง

คลาสเทียบกับเนมสเปซอินสแตนซ์

เพื่อทำความเข้าใจว่าเกิดอะไรขึ้นที่นี่เรามาพูดคุยสั้น ๆ เกี่ยวกับ เนมสเปซ Python .

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

ขึ้นอยู่กับบริบทคุณอาจต้องเข้าถึงเนมสเปซโดยใช้ dot syntax (เช่น object.name_from_objects_namespace) หรือเป็นตัวแปรโลคัล (เช่น object_from_namespace) เป็นตัวอย่างที่เป็นรูปธรรม:

class MyClass(object): ## No need for dot syntax class_var = 1 def __init__(self, i_var): self.i_var = i_var ## Need dot syntax as we've left scope of class namespace MyClass.class_var ## 1

คลาส Python และ อินสแตนซ์ของคลาสแต่ละคลาสมีเนมสเปซที่แตกต่างกันซึ่งแสดงโดย คุณลักษณะที่กำหนดไว้ล่วงหน้า MyClass.__dict__ และ instance_of_MyClass.__dict__ ตามลำดับ

node.js ใช้ทำอะไร

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

foo = MyClass(2) ## Finds i_var in foo's instance namespace foo.i_var ## 2 ## Doesn't find class_var in instance namespace… ## So look's in class namespace (MyClass.__dict__) foo.class_var ## 1

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

def instlookup(inst, name): ## simplified algorithm... if inst.__dict__.has_key(name): return inst.__dict__[name] else: return inst.__class__.__dict__[name]

และในรูปแบบภาพ:

การค้นหาแอตทริบิวต์ในรูปแบบภาพ

คุณสมบัติของคลาสจัดการกับการมอบหมายงานอย่างไร

ด้วยเหตุนี้เราจึงเข้าใจได้ว่าแอตทริบิวต์คลาส Python จัดการกับการมอบหมายอย่างไร:

  • หากมีการตั้งค่าแอตทริบิวต์คลาสโดยการเข้าถึงคลาสจะแทนที่ค่าสำหรับ ทั้งหมด ตัวอย่าง. ตัวอย่างเช่น:

    foo = MyClass(2) foo.class_var ## 1 MyClass.class_var = 2 foo.class_var ## 2

    ในระดับเนมสเปซ… เรากำลังตั้งค่า MyClass.__dict__['class_var'] = 2 (หมายเหตุ: สิ่งนี้ ไม่ใช่รหัสที่แน่นอน (ซึ่งจะเป็น setattr(MyClass, 'class_var', 2)) เป็น __dict__ ส่งคืน a dictproxy ซึ่งเป็นกระดาษห่อหุ้มที่ไม่เปลี่ยนรูปซึ่งป้องกันการมอบหมายงานโดยตรง แต่ช่วยในการสาธิต) จากนั้นเมื่อเราเข้าถึง foo.class_var, class_var มีค่าใหม่ในเนมสเปซคลาสดังนั้นจึงส่งคืน 2

  • หากตัวแปรคลาส Paython ถูกตั้งค่าโดยการเข้าถึงอินสแตนซ์ตัวแปรนั้นจะแทนที่ค่า สำหรับอินสแตนซ์นั้นเท่านั้น . สิ่งนี้จะแทนที่ตัวแปรคลาสและเปลี่ยนเป็นตัวแปรอินสแตนซ์ที่พร้อมใช้งานโดยสัญชาตญาณ สำหรับอินสแตนซ์นั้นเท่านั้น . ตัวอย่างเช่น:

    foo = MyClass(2) foo.class_var ## 1 foo.class_var = 2 foo.class_var ## 2 MyClass.class_var ## 1

    ในระดับเนมสเปซ… เรากำลังเพิ่ม class_var แอตทริบิวต์ foo.__dict__ ดังนั้นเมื่อเราค้นหา foo.class_var เราจะส่งคืน 2 ในขณะเดียวกันอินสแตนซ์อื่น ๆ ของ MyClass จะ ไม่ มี class_var ในเนมสเปซอินสแตนซ์ดังนั้นพวกเขาจึงยังคงค้นหา class_var ใน MyClass.__dict__ และส่งกลับ 1.

ความไม่แน่นอน

คำถามแบบทดสอบ: จะเกิดอะไรขึ้นถ้าแอตทริบิวต์คลาสของคุณมี ประเภทที่ไม่แน่นอน เหรอ? คุณสามารถจัดการ (mutilate?) แอตทริบิวต์คลาสได้โดยการเข้าถึงผ่านอินสแตนซ์เฉพาะและในที่สุดก็จบลง การจัดการวัตถุอ้างอิงที่อินสแตนซ์ทั้งหมดกำลังเข้าถึง (ตามที่ระบุโดย ทิโมธีวิสแมน ).

ตัวอย่างนี้แสดงให้เห็นได้ดีที่สุด กลับไปที่ Service ฉันได้กำหนดไว้ก่อนหน้านี้และดูว่าการใช้ตัวแปรคลาสอาจนำไปสู่ปัญหาระหว่างทางได้อย่างไร

class Service(object): data = [] def __init__(self, other_data): self.other_data = other_data ...

เป้าหมายของฉันคือการมีรายการว่าง ([]) เป็นค่าเริ่มต้นสำหรับ data และสำหรับแต่ละอินสแตนซ์ของ Service เพื่อที่จะมี ข้อมูลของตัวเอง ซึ่งจะมีการเปลี่ยนแปลงเมื่อเวลาผ่านไปในแต่ละอินสแตนซ์ แต่ในกรณีนี้เราจะได้รับพฤติกรรมต่อไปนี้ (จำได้ว่า Service ใช้อาร์กิวเมนต์ other_data ซึ่งเป็นสิ่งที่กำหนดเองในตัวอย่างนี้):

s1 = Service(['a', 'b']) s2 = Service(['c', 'd']) s1.data.append(1) s1.data ## [1] s2.data ## [1] s2.data.append(2) s1.data ## [1, 2] s2.data ## [1, 2]

สิ่งนี้ไม่ดีการเปลี่ยนตัวแปรคลาสผ่านอินสแตนซ์เดียวจะเปลี่ยนตัวแปรสำหรับตัวแปรอื่น ๆ ทั้งหมด!

ในระดับเนมสเปซ… อินสแตนซ์ทั้งหมดของ Service กำลังเข้าถึงและแก้ไขรายการเดียวกันใน Service.__dict__ โดยไม่ต้องทำ data แอตทริบิวต์ในเนมสเปซอินสแตนซ์

เราสามารถแก้ไขได้โดยใช้การมอบหมาย นั่นคือแทนที่จะใช้ประโยชน์จากความไม่แน่นอนของรายการเราสามารถกำหนด Service ของเราได้ วัตถุที่จะมีรายการของตนเองดังต่อไปนี้:

s1 = Service(['a', 'b']) s2 = Service(['c', 'd']) s1.data = [1] s2.data = [2] s1.data ## [1] s2.data ## [2]

ในกรณีนี้เรากำลังเพิ่ม s1.__dict__['data'] = [1] ดังนั้นต้นฉบับ Service.__dict__['data'] ยังคงไม่เปลี่ยนแปลง

น่าเสียดายที่สิ่งนี้ต้องการ Service ผู้ใช้มีความรู้อย่างใกล้ชิดเกี่ยวกับตัวแปรและมีแนวโน้มที่จะผิดพลาด ในแง่หนึ่งเราจะพูดถึงอาการมากกว่าสาเหตุ เราต้องการสิ่งที่ถูกต้องจากการก่อสร้าง

วิธีแก้ปัญหาส่วนตัวของฉัน: หากคุณแค่ใช้ตัวแปรคลาสเพื่อกำหนดค่าเริ่มต้นให้กับตัวแปรอินสแตนซ์ Python ที่น่าจะเป็น อย่าใช้ค่าที่ไม่แน่นอน . ในกรณีนี้ทุกกรณีของ Service กำลังจะลบล้าง Service.data ด้วยแอตทริบิวต์อินสแตนซ์ของตัวเองในที่สุดดังนั้นการใช้รายการว่างเป็นค่าเริ่มต้นจะนำไปสู่จุดบกพร่องเล็ก ๆ ที่มองข้ามได้ง่าย แทนที่จะเป็นข้างต้นเราสามารถทำได้:

  1. ติดอยู่กับแอตทริบิวต์อินสแตนซ์ทั้งหมดตามที่แสดงไว้ในบทนำ
  2. หลีกเลี่ยงการใช้รายการว่าง (ค่าที่ไม่แน่นอน) เป็น 'ค่าเริ่มต้น' ของเรา:

    class Service(object): data = None def __init__(self, other_data): self.other_data = other_data ...

    แน่นอนว่าเราต้องจัดการ None อย่างเหมาะสม แต่นั่นเป็นราคาที่ต้องจ่ายเล็กน้อย

คุณควรใช้ Python Class Attributes เมื่อใด

แอตทริบิวต์ของคลาสเป็นเรื่องยุ่งยาก แต่มาดูบางกรณีที่จะมีประโยชน์:

  1. การจัดเก็บค่าคงที่ . เนื่องจากแอตทริบิวต์ของคลาสสามารถเข้าถึงได้เป็นแอตทริบิวต์ของคลาสนั้น ๆ จึงมักเป็นเรื่องดีที่จะใช้เพื่อจัดเก็บค่าคงที่เฉพาะคลาสสำหรับทั้งคลาส ตัวอย่างเช่น:

    class Circle(object): pi = 3.14159 def __init__(self, radius): self.radius = radius def area(self): return Circle.pi * self.radius * self.radius Circle.pi ## 3.14159 c = Circle(10) c.pi ## 3.14159 c.area() ## 314.159
  2. การกำหนดค่าเริ่มต้น . ตามตัวอย่างเล็กน้อยเราอาจสร้างรายการที่มีขอบเขต (กล่าวคือรายการที่สามารถเก็บองค์ประกอบได้จำนวนหนึ่งหรือน้อยกว่านั้น) และเลือกให้มีค่าเริ่มต้นสูงสุด 10 รายการ:

    class MyClass(object): limit = 10 def __init__(self): self.data = [] def item(self, i): return self.data[i] def add(self, e): if len(self.data) >= self.limit: raise Exception('Too many elements') self.data.append(e) MyClass.limit ## 10

    จากนั้นเราสามารถสร้างอินสแตนซ์ที่มีขีด จำกัด เฉพาะของตนเองได้เช่นกันโดยกำหนดให้กับ limit ของอินสแตนซ์ แอตทริบิวต์

    foo = MyClass() foo.limit = 50 ## foo can now hold 50 elements—other instances can hold 10

    สิ่งนี้จะสมเหตุสมผลก็ต่อเมื่อคุณต้องการอินสแตนซ์ทั่วไปของ MyClass เพื่อเก็บองค์ประกอบเพียง 10 รายการหรือน้อยกว่านั้นหากคุณให้อินสแตนซ์ทั้งหมดของคุณขีด จำกัด ที่แตกต่างกันดังนั้น limit ควรเป็นตัวแปรอินสแตนซ์ (โปรดจำไว้ว่า: ระวังเมื่อใช้ค่าที่ไม่แน่นอนเป็นค่าเริ่มต้นของคุณ)

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

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

    วิธีการปรับแต่งประสิทธิภาพใน sql

    โปรดทราบว่าในกรณีนี้ names จะเข้าถึงได้ในฐานะตัวแปรคลาสเท่านั้นดังนั้นค่าเริ่มต้นที่เปลี่ยนแปลงได้จึงเป็นที่ยอมรับ

    class Person(object): all_names = [] def __init__(self, name): self.name = name Person.all_names.append(name) joe = Person('Joe') bob = Person('Bob') print Person.all_names ## ['Joe', 'Bob']

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

    class Person(object): all_people = [] def __init__(self, name): self.name = name Person.all_people.append(self) joe = Person('Joe') bob = Person('Bob') print Person.all_people ## [, ]
  4. ประสิทธิภาพ (เรียงลำดับ…ดูด้านล่าง)

ที่เกี่ยวข้อง: แนวทางปฏิบัติและคำแนะนำที่ดีที่สุดของ Python โดย ApeeScape Developers

ใต้ฝากระโปรง

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

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

def called_class(): print 'Class assignment' return 2 class Bar(object): y = called_class() def __init__(self, x): self.x = x ## 'Class assignment' def called_instance(): print 'Instance assignment' return 2 class Foo(object): def __init__(self, x): self.y = called_instance() self.x = x Bar(1) Bar(2) Foo(1) ## 'Instance assignment' Foo(2) ## 'Instance assignment'

เรามอบหมายให้ Bar.y เพียงครั้งเดียว แต่ instance_of_Foo.y ทุกครั้งที่โทรไปที่ __init__.

เพื่อเป็นหลักฐานเพิ่มเติมให้ใช้ไฟล์ Python disassembler :

import dis class Bar(object): y = 2 def __init__(self, x): self.x = x class Foo(object): def __init__(self, x): self.y = 2 self.x = x dis.dis(Bar) ## Disassembly of __init__: ## 7 0 LOAD_FAST 1 (x) ## 3 LOAD_FAST 0 (self) ## 6 STORE_ATTR 0 (x) ## 9 LOAD_CONST 0 (None) ## 12 RETURN_VALUE dis.dis(Foo) ## Disassembly of __init__: ## 11 0 LOAD_CONST 1 (2) ## 3 LOAD_FAST 0 (self) ## 6 STORE_ATTR 0 (y) ## 12 9 LOAD_FAST 1 (x) ## 12 LOAD_FAST 0 (self) ## 15 STORE_ATTR 1 (x) ## 18 LOAD_CONST 0 (None) ## 21 RETURN_VALUE

เมื่อเราดูรหัสไบต์จะเห็นได้ชัดอีกครั้งว่า Foo.__init__ ต้องทำงานสองอย่างในขณะที่ Bar.__init__ ทำเพียงหนึ่ง

ในทางปฏิบัติการได้รับนี้มีลักษณะอย่างไร? ฉันจะเป็นคนแรกที่ยอมรับว่าการทดสอบเวลาขึ้นอยู่กับปัจจัยที่ไม่สามารถควบคุมได้บ่อยครั้งและความแตกต่างระหว่างกันมักอธิบายได้อย่างถูกต้อง

อย่างไรก็ตามฉันคิดว่าตัวอย่างเล็ก ๆ เหล่านี้ (รันด้วย Python เวลา module) ช่วยแสดงความแตกต่างระหว่างตัวแปรคลาสและอินสแตนซ์ดังนั้นฉันจึงรวมไว้ด้วย

วิธีเข้าถึงสถานีบลูมเบิร์ก

หมายเหตุ: ฉันใช้ MacBook Pro ที่มี OS X 10.8.5 และ Python 2.7.2

การเริ่มต้น

10000000 calls to `Bar(2)`: 4.940s 10000000 calls to `Foo(2)`: 6.043s

การเริ่มต้นของ Bar เร็วกว่าหนึ่งวินาทีดังนั้นความแตกต่างที่นี่จึงดูเหมือนมีนัยสำคัญทางสถิติ

แล้วทำไมถึงเป็นเช่นนี้? หนึ่ง เก็งกำไร คำอธิบาย: เราทำงานสองงานใน Foo.__init__ แต่เพียงหนึ่งใน Bar.__init__

การมอบหมายงาน

10000000 calls to `Bar(2).y = 15`: 6.232s 10000000 calls to `Foo(2).y = 15`: 6.855s 10000000 `Bar` assignments: 6.232s - 4.940s = 1.292s 10000000 `Foo` assignments: 6.855s - 6.043s = 0.812s

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

จากข้างบนดูเหมือน Foo ใช้เวลาประมาณ 60% ตราบเท่าที่ Bar เพื่อจัดการงาน

เหตุใดจึงเป็นเช่นนี้ หนึ่ง เก็งกำไร คำอธิบาย: เมื่อเรากำหนดให้กับ Bar(2).y อันดับแรกเราดูในเนมสเปซอินสแตนซ์ (Bar(2).__dict__[y]) ไม่พบ y จากนั้นดูในเนมสเปซคลาส (Bar.__dict__[y]) จากนั้นทำการมอบหมายที่เหมาะสม เมื่อเรากำหนดให้กับ Foo(2).y เราทำการค้นหามากกว่าครึ่งหนึ่งในขณะที่เรากำหนดให้กับอินสแตนซ์เนมสเปซ (Foo(2).__dict__[y]) ทันที

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

สรุปแล้ว

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

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

ภาคผนวก : ตัวแปรอินสแตนซ์ส่วนตัว

สิ่งหนึ่งที่ฉันอยากจะรวมไว้ แต่ไม่มีทางเข้าธรรมชาติ ...

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

ในคู่มือรูปแบบ Python ได้กล่าวไว้ว่าตัวแปร pseudo-private ควรขึ้นต้นด้วยขีดล่างคู่: '__' นี่ไม่ได้เป็นเพียงสัญญาณให้ผู้อื่นทราบว่าตัวแปรของคุณถูกกำหนดให้ได้รับการปฏิบัติแบบส่วนตัวเท่านั้น แต่ยังเป็นวิธีป้องกันการเข้าถึงอีกด้วย นี่คือสิ่งที่ฉันหมายถึง:

class Bar(object): def __init__(self): self.__zap = 1 a = Bar() a.__zap ## Traceback (most recent call last): ## File '', line 1, in ## AttributeError: 'Bar' object has no attribute '__baz' ## Hmm. So what's in the namespace? a.__dict__ {'_Bar__zap': 1} a._Bar__zap ## 1

ดูที่: แอตทริบิวต์อินสแตนซ์ __zap จะขึ้นต้นด้วยชื่อคลาสโดยอัตโนมัติเพื่อให้ได้ _Bar__zap

ในขณะที่ยังคงสามารถตั้งค่าและใช้งานได้โดยใช้ a._Bar__zap ชื่อนี้ mangling เป็นวิธีการสร้างตัวแปร 'ส่วนตัว' เนื่องจากป้องกันไม่ให้คุณ และ ไม่ให้ผู้อื่นเข้าถึงโดยบังเอิญหรือโดยไม่รู้ตัว

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

ที่เกี่ยวข้อง: ก้าวสู่ขั้นสูงมากขึ้น: หลีกเลี่ยงข้อผิดพลาดทั่วไป 10 ประการที่โปรแกรมเมอร์ Python ทำ

ทำความเข้าใจพื้นฐาน

เนมสเปซ Python คืออะไร?

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

วิธีคลาส Python กับวิธีการอินสแตนซ์: อะไรคือความแตกต่าง?

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

จะเกิดอะไรขึ้นหากมีการกำหนดทั้งแอตทริบิวต์อินสแตนซ์และแอตทริบิวต์คลาส

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

ตลาดการโอนเงินระหว่างประเทศมีการพัฒนาอย่างไร?

กระบวนการทางการเงิน

ตลาดการโอนเงินระหว่างประเทศมีการพัฒนาอย่างไร?
หนึ่งขนาดเหมาะกับบางคน: คำแนะนำสำหรับโซลูชันการออกแบบเว็บที่ตอบสนองต่อการออกแบบรูปภาพ

หนึ่งขนาดเหมาะกับบางคน: คำแนะนำสำหรับโซลูชันการออกแบบเว็บที่ตอบสนองต่อการออกแบบรูปภาพ

ส่วนหน้าของเว็บ

โพสต์ยอดนิยม
Nvidia Shield - สิ่งที่แตกต่างบนคอนโซลเกม Android
Nvidia Shield - สิ่งที่แตกต่างบนคอนโซลเกม Android
แผ่นโกงการจัดการโครงการ
แผ่นโกงการจัดการโครงการ
เริ่มต้นใช้งาน Microservices: บทช่วยสอน Dropwizard
เริ่มต้นใช้งาน Microservices: บทช่วยสอน Dropwizard
การแยกการเรียกเก็บเงิน: เรื่องของการเพิ่มประสิทธิภาพ API ภายใน GraphQL
การแยกการเรียกเก็บเงิน: เรื่องของการเพิ่มประสิทธิภาพ API ภายใน GraphQL
กรณีศึกษา: การใช้ ApeeScape เพื่อม้วนปลาใหญ่
กรณีศึกษา: การใช้ ApeeScape เพื่อม้วนปลาใหญ่
 
การประมาณต้นทุนซอฟต์แวร์ในการจัดการโครงการแบบ Agile
การประมาณต้นทุนซอฟต์แวร์ในการจัดการโครงการแบบ Agile
แชทล่ม - เมื่อ Chatbot ล้มเหลว
แชทล่ม - เมื่อ Chatbot ล้มเหลว
ที่ปรึกษาการระดมทุนกับนายหน้า - ตัวแทนจำหน่าย
ที่ปรึกษาการระดมทุนกับนายหน้า - ตัวแทนจำหน่าย
ทำให้ Web Front-end เชื่อถือได้ด้วย Elm
ทำให้ Web Front-end เชื่อถือได้ด้วย Elm
คู่มือสำหรับนักลงทุนเกี่ยวกับน้ำมันปาล์ม
คู่มือสำหรับนักลงทุนเกี่ยวกับน้ำมันปาล์ม
โพสต์ยอดนิยม
  • บอทในความขัดแย้งคืออะไร
  • โปรแกรมโปรแกรม c++
  • วิธีรับโทเค็น jwt
  • บริษัท c และ บริษัท ต่างๆเป็นนิติบุคคลที่เสียภาษีแยกต่างหากซึ่งจ่ายภาษีจากรายได้ของตนเอง
  • วิธีรับ power pivot
  • หมายเลขบัตรเครดิตของใครบางคนที่ฉันสามารถใช้ได้
  • ที่นั่น vs คนเดียว vs ฉัน
หมวดหมู่
  • การจัดการวิศวกรรม
  • Kpi และ Analytics
  • เทคโนโลยี
  • ว่องไว
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt