Είναι ένας απλός, κομψός τρόπος για να καθορίσει μονήρεις εκεί;

ψήφοι
363

Φαίνεται να είναι πολλοί τρόποι για να καθορίσει υπάρχουν μονήρεις στην Python. Είναι μια γνώμη συναίνεση σχετικά με Υπερχείλιση στοίβας εκεί;

Δημοσιεύθηκε 28/08/2008 στις 10:03
πηγή χρήστη
Σε άλλες γλώσσες...                            


22 απαντήσεις

ψήφοι
2

Όντας σχετικά νέος σε Python δεν είμαι σίγουρος ποιο είναι το πιο κοινό ιδίωμα είναι, αλλά το πιο απλό πράγμα που μπορώ να σκεφτώ είναι απλά χρησιμοποιώντας μια μονάδα αντί για μια τάξη. Τι θα ήταν μεθόδων παράδειγμα σχετικά με την τάξη σας να γίνει μόνο λειτουργίες της μονάδας και τα δεδομένα γίνεται μόνο μεταβλητές στην ενότητα αντί των μελών της κατηγορίας. Υποψιάζομαι ότι αυτή είναι η pythonic προσέγγιση για την επίλυση του είδος του προβλήματος που οι άνθρωποι χρησιμοποιούν μονήρεις για.

Αν θέλετε πραγματικά μια τάξη μονήρεις, υπάρχει μια λογική εφαρμογή που περιγράφεται στο πρώτο χτύπημα στο Google για «Python μονήρεις», και συγκεκριμένα:

class Singleton:
    __single = None
    def __init__( self ):
        if Singleton.__single:
            raise Singleton.__single
        Singleton.__single = self

Αυτό φαίνεται να κάνει το κόλπο.

Απαντήθηκε 28/08/2008 στις 10:09
πηγή χρήστη

ψήφοι
301

Δεν βλέπω πραγματικά την ανάγκη, ως μονάδα με λειτουργίες (και όχι μια κατηγορία) θα χρησιμεύσει επίσης ως μονήρεις. Όλες οι μεταβλητές της θα πρέπει να συνδέεται με τη μονάδα, η οποία δεν μπορεί να αρχικοποιείται κατ 'επανάληψη ούτως ή άλλως.

Αν θέλετε να χρησιμοποιήσετε μια τάξη, δεν υπάρχει κανένας τρόπος για τη δημιουργία ιδιαίτερα μαθήματα ή ιδιωτική κατασκευαστές στην Python, έτσι ώστε να μην μπορεί να προστατεύσει από πολλαπλά στιγμιότυπα, εκτός από απλά μέσω σύμβασης με τη χρήση του API σας. Θα ήθελα ακόμα μόλις τεθεί μεθόδους σε μια μονάδα, και να εξετάσει τη μονάδα ως μονήρεις.

Απαντήθηκε 28/08/2008 στις 10:10
πηγή χρήστη

ψήφοι
7

Εδώ είναι ένα παράδειγμα από τον Peter Norvig της Python IAQ Πώς μπορώ να κάνω το μοτίβο Singleton στην Python; (Θα πρέπει να χρησιμοποιήσετε τη λειτουργία αναζήτησης του browser σας για να βρείτε αυτό το θέμα, δεν υπάρχει άμεση σύνδεση, sorry)

Επίσης Bruce Eckel έχει ένα άλλο παράδειγμα, στο βιβλίο του σκέψης σε Python (και πάλι δεν υπάρχει άμεση σύνδεση με τον κωδικό)

Απαντήθηκε 28/08/2008 στις 10:13
πηγή χρήστη

ψήφοι
101

Μια ελαφρώς διαφορετική προσέγγιση για την υλοποίηση του Singleton σε Python είναι η Borg σχέδιο από τον Alex Martelli (Google εργαζομένων και Python ιδιοφυΐα).

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state

Έτσι, αντί να αναγκάζει όλες τις περιπτώσεις να έχουν την ίδια ταυτότητα, μοιράζονται κατάσταση.

Απαντήθηκε 28/08/2008 στις 15:53
πηγή χρήστη

ψήφοι
73

Η προσέγγιση μονάδα λειτουργεί καλά. Αν ήμουν απολύτως ανάγκη μια μονήρεις προτιμώ την προσέγγιση μετακλάση.

class Singleton(type):
    def __init__(cls, name, bases, dict):
        super(Singleton, cls).__init__(name, bases, dict)
        cls.instance = None 

    def __call__(cls,*args,**kw):
        if cls.instance is None:
            cls.instance = super(Singleton, cls).__call__(*args, **kw)
        return cls.instance

class MyClass(object):
    __metaclass__ = Singleton
Απαντήθηκε 28/08/2008 στις 20:39
πηγή χρήστη

ψήφοι
14

Η μία φορά έγραψα ένα μονήρεις στην Python θα χρησιμοποιηθεί σε μια τάξη όπου όλοι οι συναρτήσεις-μέλη είχαν την διακοσμητής classmethod.

class foo:
  x = 1

  @classmethod
  def increment(cls, y = 1):
    cls.x += y
Απαντήθηκε 29/08/2008 στις 20:15
πηγή χρήστη

ψήφοι
3

Το μοτίβο Singleton υλοποιείται με την Python ευγένεια του ActiveState.

Μοιάζει με το τέχνασμα είναι να βάλει την τάξη που υποτίθεται ότι έχουν μόνο ένα παράδειγμα μέσα από μια άλλη κατηγορία.

Απαντήθηκε 03/09/2008 στις 21:54
πηγή χρήστη

ψήφοι
8

Υπάρχουν επίσης μερικά ενδιαφέροντα άρθρα σχετικά με το blog Δοκιμές Google, συζητώντας γιατί μονήρεις είναι / μπορεί να είναι κακό και είναι ένα αντι-μοτίβο:

Απαντήθηκε 15/09/2008 στις 08:47
πηγή χρήστη

ψήφοι
12

Είμαι πολύ σίγουρος γι 'αυτό, αλλά (δεν επιβάλλονται singletons9 «σύμβαση μονήρεις» χρήσεις του έργου μου, ότι είναι, αν έχω μια κατηγορία που ονομάζεται DataController, ορίζω αυτό στην ίδια ενότητα:

_data_controller = None
def GetDataController():
    global _data_controller
    if _data_controller is None:
        _data_controller = DataController()
    return _data_controller

Δεν είναι κομψό, δεδομένου ότι είναι ένα πλήρες έξι γραμμές. Αλλά όλα μονήρεις κυήσεις μου χρησιμοποιούν αυτό το μοτίβο, και είναι τουλάχιστον πολύ σαφής (η οποία είναι pythonic).

Απαντήθηκε 22/08/2009 στις 01:44
πηγή χρήστη

ψήφοι
173

Μπορείτε να παρακάμψετε τη __new__μέθοδο ως εξής:

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(
                                cls, *args, **kwargs)
        return cls._instance


if __name__ == '__main__':
    s1 = Singleton()
    s2 = Singleton()
    if (id(s1) == id(s2)):
        print "Same"
    else:
        print "Different"
Απαντήθηκε 27/11/2009 στις 20:37
πηγή χρήστη

ψήφοι
2
class Singleton(object[,...]):

    staticVar1 = None
    staticVar2 = None

    def __init__(self):
        if self.__class__.staticVar1==None :
            # create class instance variable for instantiation of class
            # assign class instance variable values to class static variables
        else:
            # assign class static variable values to class instance variables
Απαντήθηκε 17/12/2009 στις 16:10
πηγή χρήστη

ψήφοι
40

Δείτε αυτό εφαρμογή από PEP318 , για την εφαρμογή της μονήρεις μοτίβο με ένα διακοσμητή:

def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

@singleton
class MyClass:
    ...
Απαντήθηκε 02/05/2010 στις 03:47
πηγή χρήστη

ψήφοι
5

Νομίζω ότι αναγκάζοντας μια τάξη ή μια παρουσία να είναι μονήρεις είναι υπερβολή. Προσωπικά, μου αρέσει να καθοριστεί μια κανονική instantiable τάξη, μια ημι-ιδιωτική αναφοράς, και μια απλή λειτουργία του εργοστασίου.

class NothingSpecial:
    pass

_the_one_and_only = None

def TheOneAndOnly():
    global _the_one_and_only
    if not _the_one_and_only:
        _the_one_and_only = NothingSpecial()
    return _the_one_and_only

Ή αν δεν υπάρχει πρόβλημα με το στιγμιότυπο, όταν η μονάδα εισάγεται για πρώτη φορά:

class NothingSpecial:
    pass

THE_ONE_AND_ONLY = NothingSpecial()

Με αυτόν τον τρόπο μπορείτε να γράψετε εξετάσεις κατά φρέσκο ​​περιπτώσεις χωρίς παρενέργειες, και δεν υπάρχει καμία ανάγκη για το πασπάλισμα της μονάδας με την παγκόσμια δηλώσεις, και αν χρειαστεί μπορείτε να αντλήσει παραλλαγές στο μέλλον.

Απαντήθηκε 27/07/2011 στις 13:00
πηγή χρήστη

ψήφοι
263

Εδώ είναι η δική μου υλοποίηση των μονήρεις κυήσεις. Το μόνο που έχετε να κάνετε είναι να διακοσμήσετε την τάξη? για να πάρει το μονήρεις, τότε πρέπει να χρησιμοποιήσετε τη Instanceμέθοδο. Εδώ είναι ένα παράδειγμα:

@Singleton
class Foo:
   def __init__(self):
       print 'Foo created'

f = Foo() # Error, this isn't how you get the instance of a singleton

f = Foo.instance() # Good. Being explicit is in line with the Python Zen
g = Foo.instance() # Returns already created instance

print f is g # True

Και εδώ είναι ο κώδικας:

class Singleton:
    """
    A non-thread-safe helper class to ease implementing singletons.
    This should be used as a decorator -- not a metaclass -- to the
    class that should be a singleton.

    The decorated class can define one `__init__` function that
    takes only the `self` argument. Also, the decorated class cannot be
    inherited from. Other than that, there are no restrictions that apply
    to the decorated class.

    To get the singleton instance, use the `instance` method. Trying
    to use `__call__` will result in a `TypeError` being raised.

    """

    def __init__(self, decorated):
        self._decorated = decorated

    def instance(self):
        """
        Returns the singleton instance. Upon its first call, it creates a
        new instance of the decorated class and calls its `__init__` method.
        On all subsequent calls, the already created instance is returned.

        """
        try:
            return self._instance
        except AttributeError:
            self._instance = self._decorated()
            return self._instance

    def __call__(self):
        raise TypeError('Singletons must be accessed through `instance()`.')

    def __instancecheck__(self, inst):
        return isinstance(inst, self._decorated)
Απαντήθηκε 08/09/2011 στις 10:46
πηγή χρήστη

ψήφοι
0

Σε περίπτωση που δεν θέλετε τη λύση μετακλάση με βάση το παραπάνω, και δεν σας αρέσει η προσέγγιση διακοσμητή με βάση απλές λειτουργίες (π.χ. επειδή σε αυτή την περίπτωση στατικές μεθόδους για την κατηγορία μονήρεις δεν θα λειτουργήσει), ο συμβιβασμός αυτός λειτουργεί:

class singleton(object):
  """Singleton decorator."""

  def __init__(self, cls):
      self.__dict__['cls'] = cls

  instances = {}

  def __call__(self):
      if self.cls not in self.instances:
          self.instances[self.cls] = self.cls()
      return self.instances[self.cls]

  def __getattr__(self, attr):
      return getattr(self.__dict__['cls'], attr)

  def __setattr__(self, attr, value):
      return setattr(self.__dict__['cls'], attr, value)
Απαντήθηκε 28/10/2011 στις 10:52
πηγή χρήστη

ψήφοι
2

απλή λύση μου που βασίζεται στην προκαθορισμένη τιμή των παραμέτρων λειτουργίας.

def getSystemContext(contextObjList=[]):
    if len( contextObjList ) == 0:
        contextObjList.append( Context() )
        pass
    return contextObjList[0]

class Context(object):
    # Anything you want here
Απαντήθηκε 28/11/2011 στις 14:15
πηγή χρήστη

ψήφοι
9

Η δημιουργία ενός διακοσμητή μονήρεις (γνωστός και ως έναν σχολιασμό) είναι ένας κομψός τρόπος, αν θέλετε να διακοσμήσετε (σχολιάζω) τάξεις να πάμε μπροστά. Στη συνέχεια, μπορείτε απλά βάλτε @singleton πριν ορισμό τάξη σας.

def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

@singleton
class MyClass:
    ...
Απαντήθηκε 22/02/2012 στις 23:16
πηγή χρήστη

ψήφοι
2

Εντάξει, μονήρεις θα μπορούσε να είναι καλό ή κακό, το ξέρω. Αυτή είναι η εφαρμογή μου, και εγώ απλά να επεκτείνει μια κλασική προσέγγιση για την εισαγωγή μια κρύπτη στο εσωτερικό και να παράγουν πολλές περιπτώσεις διαφορετικού τύπου ή, πολλές περιπτώσεις ίδιου τύπου, αλλά με διαφορετικά επιχειρήματα.

Μου ζήτησε Singleton_group, γιατί ομάδες παρόμοιες περιπτώσεις μαζί και να εμποδίσει το αντικείμενο της ίδιας κατηγορίας, με τα ίδια επιχειρήματα, θα μπορούσαν να δημιουργηθούν:

# Peppelinux's cached singleton
class Singleton_group(object):
    __instances_args_dict = {}
    def __new__(cls, *args, **kwargs):
        if not cls.__instances_args_dict.get((cls.__name__, args, str(kwargs))):
            cls.__instances_args_dict[(cls.__name__, args, str(kwargs))] = super(Singleton_group, cls).__new__(cls, *args, **kwargs)
        return cls.__instances_args_dict.get((cls.__name__, args, str(kwargs)))


# It's a dummy real world use example:
class test(Singleton_group):
    def __init__(self, salute):
        self.salute = salute

a = test('bye')
b = test('hi')
c = test('bye')
d = test('hi')
e = test('goodbye')
f = test('goodbye')

id(a)
3070148780L

id(b)
3070148908L

id(c)
3070148780L

b == d
True


b._Singleton_group__instances_args_dict

{('test', ('bye',), '{}'): <__main__.test object at 0xb6fec0ac>,
 ('test', ('goodbye',), '{}'): <__main__.test object at 0xb6fec32c>,
 ('test', ('hi',), '{}'): <__main__.test object at 0xb6fec12c>}

Κάθε αντικείμενο φέρει το μονήρεις προσωρινή μνήμη ... Αυτό θα μπορούσε να είναι κακό, αλλά λειτουργεί μεγάλο για κάποιους :)

Απαντήθηκε 28/02/2012 στις 21:42
πηγή χρήστη

ψήφοι
11

Η τεκμηρίωση Python κάνει καλύψει αυτό:

class Singleton(object):
    def __new__(cls, *args, **kwds):
        it = cls.__dict__.get("__it__")
        if it is not None:
            return it
        cls.__it__ = it = object.__new__(cls)
        it.init(*args, **kwds)
        return it
    def init(self, *args, **kwds):
        pass

Θα ήθελα να το ξαναγράψει πιθανώς να μοιάζουν περισσότερο με αυτό:

class Singleton(object):
    """Use to create a singleton"""
    def __new__(cls, *args, **kwds):
        """
        >>> s = Singleton()
        >>> p = Singleton()
        >>> id(s) == id(p)
        True
        """
        self = "__self__"
        if not hasattr(cls, self):
            instance = object.__new__(cls)
            instance.init(*args, **kwds)
            setattr(cls, self, instance)
        return getattr(cls, self)

    def init(self, *args, **kwds):
        pass

Θα πρέπει να είναι σχετικά καθαρό για να επεκτείνει αυτό:

class Bus(Singleton):
    def init(self, label=None, *args, **kwds):
        self.label = label
        self.channels = [Channel("system"), Channel("app")]
        ...
Απαντήθηκε 17/07/2012 στις 07:38
πηγή χρήστη

ψήφοι
1
class Singeltone(type):
    instances = dict()

    def __call__(cls, *args, **kwargs):
        if cls.__name__ not in Singeltone.instances:            
            Singeltone.instances[cls.__name__] = type.__call__(cls, *args, **kwargs)
        return Singeltone.instances[cls.__name__]


class Test(object):
    __metaclass__ = Singeltone


inst0 = Test()
inst1 = Test()
print(id(inst1) == id(inst0))
Απαντήθηκε 15/08/2012 στις 08:08
πηγή χρήστη

ψήφοι
25

Καθώς η αποδεκτή απάντηση , λέει, ο πιο ιδιωματικές τρόπος είναι απλά να χρησιμοποιήσετε μια μονάδα .

Με αυτό κατά νου, εδώ είναι μια απόδειξη της έννοιας:

def singleton(cls):
    obj = cls()
    # Always return the same object
    cls.__new__ = staticmethod(lambda cls: obj)
    # Disable __init__
    try:
        del cls.__init__
    except AttributeError:
        pass
    return cls

Δείτε το μοντέλο δεδομένων Python για περισσότερες λεπτομέρειες σχετικά __new__.

Παράδειγμα:

@singleton
class Duck(object):
    pass

if Duck() is Duck():
    print "It works!"
else:
    print "It doesn't work!"

Σημειώσεις:

  1. Μπορείτε να χρησιμοποιήσετε τις κατηγορίες νέου τύπου (προέρχονται από object) γι 'αυτό.

  2. Η μονήρεις ξεκινά όταν ορίζεται, αντί για την πρώτη φορά που χρησιμοποιείται.

  3. Αυτό είναι μόνο ένα παράδειγμα παιχνίδι. Δεν έχω πάρει ποτέ στην πραγματικότητα αυτό στον κώδικα παραγωγής, και δεν σκοπεύουν να.

Απαντήθηκε 12/10/2012 στις 01:13
πηγή χρήστη

ψήφοι
2

ετεροθαλής αδελφός Singleton του

Συμφωνώ απόλυτα με staale και αφήνω εδώ ένα δείγμα της δημιουργίας ενός μονήρεις ετεροθαλής αδελφός:

class void:pass
a = void();
a.__class__ = Singleton

aθα αναφέρει τώρα ότι είναι της ίδιας κατηγορίας με μονήρεις, ακόμη και αν αυτό δεν μοιάζει με αυτό. Έτσι μονήρεις κυήσεις, χρησιμοποιώντας πολύπλοκες κατηγορίες καταλήγουν ανάλογα με το που δεν χάος πολύ μαζί τους.

Όντας έτσι, μπορούμε να έχουμε το ίδιο αποτέλεσμα και να χρησιμοποιούν απλούστερα πράγματα, όπως μια μεταβλητή ή μια μονάδα. Παρόλα αυτά, αν θέλουμε να χρησιμοποιήσετε τις κατηγορίες για λόγους σαφήνειας και επειδή στην Python μια τάξη είναι ένα αντικείμενο , έτσι έχουμε ήδη το αντικείμενο (όχι και χάρη, αλλά θα κάνει ακριβώς ήθελε).

class Singleton:
    def __new__(cls): raise AssertionError # Singletons can't have instances

Εκεί έχουμε ένα ωραίο σφάλμα ισχυρισμό αν προσπαθήσουμε να δημιουργήσουμε ένα παράδειγμα, και μπορούμε να αποθηκεύσουμε σε παράγωγα στατικά μέλη και να κάνετε αλλαγές σε αυτά κατά το χρόνο εκτέλεσης (μου αρέσει Python). Αυτό το αντικείμενο είναι τόσο καλή όσο άλλες περίπου το ήμισυ αδελφούς (μπορείτε να τα δημιουργήσετε, αν θέλετε), ωστόσο θα έχουν την τάση να τρέχει πιο γρήγορα λόγω της απλότητας.

Απαντήθηκε 11/01/2013 στις 16:10
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more