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


11

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

มีคำถามที่คล้ายกันแต่มีจุดเน้นที่แตกต่าง:

  1. มันเกี่ยวกับการจัดกลุ่มตัวแปรส่วนกลางและฟังก์ชันในคลาสและ
  2. มันไม่ได้เป็นงูหลามที่เฉพาะเจาะจง หลังหมายถึงมันไม่ได้พิจารณาความจริงที่ว่าคลาส (ใน Python) เป็นวัตถุด้วย

UPDATE:

ใน Python ฉันสามารถทำสิ่งต่อไปนี้กับทั้งคลาสและวัตถุ:

class A(object):
    pass

A.some_state_var = True
# Then later
A.some_state_var = False


my_a = A()

my_a.some_state_var = True
# Then later
my_a.some_state_var = False

ดังนั้นฉันไม่เห็นวิธีการเลือกระหว่างคลาสและอินสแตนซ์ของคลาสนั้นเกี่ยวกับสถานะ (ใน Python) ฉันสามารถรักษาสถานะด้วยสองอย่างใดอย่างหนึ่ง

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

นอกจากนี้ยังไม่มากนักเกี่ยวกับการสร้างประเภทใหม่

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

คำตอบ:


16

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

ดังนั้นนี่คือ:

class Singleton:
    '''don't bother instantiating me'''
    clsvar1 = 'foo'

    @classmethod
    def foobar(cls, *args, **kwargs):
        if condition():
            cls.clsvar1 = 'bar'

เมื่อเทียบกับสิ่งนี้

class Singleton:
    '''instantiate and use me'''
    def __init__(self):
        self.var1 = 'foo'

    def foobar(self, *args, **kwargs):
        if condition():
            self.var1 = 'bar'

คำแนะนำ

แน่นอนว่าฉันจะชอบคนที่ตั้งใจให้เป็นอินสแตนซ์ เมื่อคุณสร้าง "ประเภทของสิ่ง" ที่บอกเป็นนัยว่าคุณสร้างสิ่งประเภทนั้น

แรงจูงใจคือการจัดกลุ่มรหัสและข้อมูลที่เกี่ยวข้องและมีส่วนต่อประสานกับมัน

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

var1 ='foo'

def foobar(*args, **kwargs):
    global var1
    if condition():
        var1 = 'bar'

ดังนั้นการใช้งานจะเป็น:

from modules.singleton import Singleton
Singleton.foobar()

หรือ

from modules.singleton import Singleton
the_singleton = Singleton()
the_singleton.foobar()

ทำเช่นนี้:

from modules import singleton
singleton.foobar()

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

อีกหนึ่งข้อสังเกต: คุณเขียนว่า "เนื่องจากสิ่งที่คุณต้องการคือเนมสเปซ" สิ่งที่ฉันต้องการคือการจัดกลุ่มรหัสที่เกี่ยวข้องเช่นฟังก์ชั่นและข้อมูลในที่เดียวและมีส่วนต่อประสานกับมัน มันไม่ได้เกี่ยวกับการสร้าง "ประเภท" มากนัก ในระหว่างการออกแบบสิ่งนี้จะส่งผลให้คลาสมีคลาสไดอะแกรมต่อไปใช่ไหม
langlauf.io

2

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

นี่คือหนึ่งในสิ่งเหล่านั้นที่จะทำให้เกิดสงครามศาสนาหากคุณได้รับมันมาก

แต่โดยทั่วไปแล้วการฝึกฝนที่ฉันได้เห็นหลายครั้งก็คือวิธีการเรียนควรเกี่ยวข้องกับตัวเองเฉพาะกับการสร้างอินสแตนซ์ของคลาสนั้น

หากคุณคิดว่าคลาสคืออะไรจุดประสงค์ / พฤติกรรมของมันคืออะไร วัตถุประสงค์ของชั้นเรียนคือการสร้างอินสแตนซ์ของวัตถุที่อยู่บนพื้นฐานของตัวเอง มันเป็นพิมพ์เขียวที่สามารถสร้างอาคารได้ คลาส "ผู้ใช้" สร้างวัตถุ "ผู้ใช้" คลาส "Dog" สร้างวัตถุ "dog" ฯลฯ

ให้สิ่งนี้เป็นพฤติกรรมของคลาสที่เหมาะสมแล้ววิธีการที่คุณเพิ่มในคลาส "X" จะเกี่ยวกับตัวเองด้วยการสร้างวัตถุ "x"

ดังนั้นแม้ว่าคุณจะต้องการวัตถุ "x" เพียงชิ้นเดียวคุณก็ควรจะทำการติดตั้งมัน

การเพิ่มวิธีการในคลาส X ที่ไม่เกี่ยวข้องกับการสร้างอินสแตนซ์ของวัตถุ "x" สามารถทำให้เกิดความสับสนในโค้ดที่ไม่คาดคิด มีตัวอย่างมากมายในโลกแห่งความเป็นจริงที่ผู้คนได้ทำสิ่งนี้อยู่แล้ว แต่อย่างที่ฉันบอกว่าเส้นทางนั้นนำไปสู่สงครามศาสนา

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