سؤال

ولدي فئة أساسية مع خاصية منها (طريقة الحصول على) I تريد الكتابة في فئة فرعية. كانت فكرتي الأولى شيئا مثل:

class Foo(object):
    def _get_age(self):
        return 11

    age = property(_get_age)


class Bar(Foo):
    def _get_age(self):
        return 44

وهذا لا يعمل (الفئة الفرعية bar.age يعود 11). لقد وجدت الحل مع تعبير لامدا التي تعمل:

age = property(lambda self: self._get_age())

وهكذا هل هذا هو الحل المناسب لاستخدام خصائص والكتابة لهم في فئة فرعية، أم أن هناك طرق المفضلة أخرى للقيام بذلك؟

هل كانت مفيدة؟

المحلول

وأنا ببساطة تفضل تكرار property() وكذلك سوف تكرار الديكور @classmethod عندما تجاوز طريقة الطبقة.

ورغم أن هذا يبدو مطول جدا، على الأقل بالنسبة لمعايير بيثون، قد تلاحظ:

1) لخصائص للقراءة فقط، property يمكن استخدام الديكور:

class Foo(object):
    @property
    def age(self):
        return 11

class Bar(Foo):
    @property
    def age(self):
        return 44

2) في بيثون 2.6، نمت خصائص زوج من أساليب setter و deleter والتي يمكن استخدامها لتطبيق الخصائص العامة الاختصار متاحة بالفعل للقراءة فقط منها:

class C(object):
    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

نصائح أخرى

وأنا لا أوافق أن الإجابة المختارة هي الطريقة المثلى للسماح لتجاوز أساليب الخاصية. إذا كنت تتوقع أن حاصل على واضعي إلى أن يتم تجاوز، ثم يمكنك استخدام امدا لتوفير الوصول إلى النفس، مع شيء من هذا القبيل lambda self: self.<property func>.

وهذا يعمل (على الأقل) لإصدارات بيثون 2،4-3،6.

إذا كان أي شخص يعرف طريقة للقيام بذلك مع باستخدام الممتلكات والديكور بدلا من مكالمة الملكية المباشرة ()، أود أن أسمع ذلك!

مثال:

class Foo(object):
    def _get_meow(self):
        return self._meow + ' from a Foo'
    def _set_meow(self, value):
        self._meow = value
    meow = property(fget=lambda self: self._get_meow(),
                    fset=lambda self, value: self._set_meow(value))

وبهذه الطريقة، تجاوز يمكن القيام بها بسهولة:

class Bar(Foo):
    def _get_meow(self):
        return super(Bar, self)._get_meow() + ', altered by a Bar'

وذلك ما يلي:

>>> foo = Foo()
>>> bar = Bar()
>>> foo.meow, bar.meow = "meow", "meow"
>>> foo.meow
"meow from a Foo"
>>> bar.meow
"meow from a Foo, altered by a Bar"

ولقد اكتشفت هذا في <لأ href = "http://www.kylev.com/2004/10/13/fun-with-python-properties/" يختلط = "noreferrer" عنوان = "OMG انها قديمة!" > المهوس في اللعب .

وهناك طريقة أخرى للقيام بذلك، دون الحاجة إلى إنشاء أي دروس إضافية. واضاف لقد طريقة مجموعة لاظهار ما كنت تفعل لو كنت تجاوز سوى واحد من اثنين:

class Foo(object):
    def _get_age(self):
        return 11

    def _set_age(self, age):
        self._age = age

    age = property(_get_age, _set_age)


class Bar(Foo):
    def _get_age(self):
        return 44

    age = property(_get_age, Foo._set_age)

وهذا هو مثال مفتعلة جدا، ولكن يجب عليك الحصول على هذه الفكرة.

نعم، هذا هو السبيل لتحقيق ذلك. تنفيذ إعلان الملكية في ذلك الوقت يتم تنفيذ الفئة 'تعريف الوالدين، مما يعني أنه لا يمكن إلا أن "رؤية" إصدارات الطرق التي توجد في الفئة الأصل. وذلك عند إعادة تعريف واحد أو أكثر من هذه الأساليب على فئة الأطفال، وتحتاج إلى إعادة يعلن-الممتلكات باستخدام 'نسخة طبقة الطفل من طريقة (ق).

وأنا أتفق مع الحل الخاص بك، والذي يبدو وسيلة القالب على ذبابة. هذه المقالة تتعامل مع مشكلتك، ويوفر بالضبط الحل.

وشيء من هذا القبيل سيعمل

class HackedProperty(object):
    def __init__(self, f):
        self.f = f
    def __get__(self, inst, owner):    
        return getattr(inst, self.f.__name__)()

class Foo(object):
    def _get_age(self):
        return 11
    age = HackedProperty(_get_age)

class Bar(Foo):
    def _get_age(self):
        return 44

print Bar().age
print Foo().age

@ السيد [ب الصورة ولكن مع الديكور.

class Foo(object):
    def _get_meow(self):
        return self._meow + ' from a Foo'
    def _set_meow(self, value):
        self._meow = value
    @property
    def meow(self):
        return self._get_meow()
    @meow.setter
    def meow(self, value):
        self._set_meow(value)

وبهذه الطريقة، تجاوز يمكن القيام بها بسهولة:

class Bar(Foo):
    def _get_meow(self):
        return super(Bar, self)._get_meow() + ', altered by a Bar'

وأنا واجهت مشاكل تعيين خاصية في فئة أصل من فئة الأطفال. وworkround التالية تمتد خاصية أحد الوالدين ولكنه يفعل ذلك بواسطة استدعاء الأسلوب _set_age الأم مباشرة. يجب أن تكون التجاعيد دائما الصحيح. فمن الرغم قليلا javathonic.

import threading


class Foo(object):
    def __init__(self):
        self._age = 0

    def _get_age(self):
        return self._age

    def _set_age(self, age):
        self._age = age

    age = property(_get_age, _set_age)


class ThreadsafeFoo(Foo):

    def __init__(self):
        super(ThreadsafeFoo, self).__init__()
        self.__lock = threading.Lock()
        self.wrinkled = False

    def _get_age(self):
        with self.__lock:
             return super(ThreadsafeFoo, self).age

    def _set_age(self, value):
        with self.__lock:
            self.wrinkled = True if value > 40 else False
            super(ThreadsafeFoo, self)._set_age(value)

    age = property(_get_age, _set_age)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top