Rop ප්‍රොපර්ටි සැරසිලි කරුවා ක්‍රියා කරන්නේ කෙසේද?


1010

බිල්ට් ශ්‍රිතය propertyක්‍රියා කරන ආකාරය තේරුම් ගැනීමට මම කැමතියි . මා ව්‍යාකූල කරන දෙය නම් propertyඑය සැරසිලි කරුවෙකු ලෙසද භාවිතා කළ හැකි නමුත් එය තර්ක විතර්ක කරන්නේ ගොඩනංවන ලද ශ්‍රිතයක් ලෙස භාවිතා කරන විට මිස සැරසිලි කරුවෙකු ලෙස භාවිතා කරන විට නොවේ.

මෙම උදාහරණය ප්‍රලේඛනයෙන් :

class C(object):
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x
    def setx(self, value):
        self._x = value
    def delx(self):
        del self._x
    x = property(getx, setx, delx, "I'm the 'x' property.")

property'තර්ක s getx, setx, delxහා ලේඛය string.

පහත කේතයේ propertyසැරසිලි කරුවෙකු ලෙස භාවිතා කරයි. එහි වස්තුව xශ්‍රිතය වන නමුත් ඉහත කේතය තුළ තර්ක තුළ වස්තු ශ්‍රිතයක් සඳහා ස්ථානයක් නොමැත.

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

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

    @x.deleter
    def x(self):
        del self._x

හා, ආකාරය වේ x.setterහා x.deleterසැරසිලි නිර්මාණය? මම අන්දමන්ද වෙලා.



3
propertyඇත්ත වශයෙන්ම පංතියක් (ශ්‍රිතයක් නොවේ), __init__()ඔබ වස්තුවක් සෑදීමේදී එය බොහෝ විට ක්‍රමය ලෙස හැඳින්වුවද , ඇත්ත වශයෙන්ම. help(property)පර්යන්තයෙන් භාවිතා කිරීම තීක්ෂ්ණ බුද්ධියකි. helpකිසියම් හේතුවක් නිසා පන්තියකි.
Brōtsyorfuzthrāx

මෙම සබැඳිය ඊට හොඳ උදාහරණයක් සපයයි යැයි මම සිතමි: [දේපල] ( magazinedev.com/14893/python-property-decorator )
ෂෙන්ග් බී

4
අවුරුදු 2 ක් වයසැති නූල්, නමුත් තවමත්: සෑම දෙයක්ම පන්තියකි. පන්ති පවා.
ආටෙමිස් තවමත් විශ්වාස නොකරයි SE

2
මෙය මටත් ව්‍යාකූල විය. අන්තිමේදී මට එය බිඳ දැමිය හැකි ලිපියක් හමු විය. මම හිතනවා මේක වෙන කෙනෙකුට උදව් කරයි කියලා. programiz.com/python-programming/property මම වෙබ් අඩවිය සමඟ කිසිදු ආකාරයකින් අනුබද්ධ නොවේ.
jjwdesign

Answers:


1034

මෙම property()උත්සවය සඳහා විශේෂ නැවත descriptor වස්තුව :

>>> property()
<property object at 0x10ff07940>

අමතර ක්‍රම ඇත්තේ මෙම වස්තුවයි :

>>> property().getter
<built-in method getter of property object at 0x10ff07998>
>>> property().setter
<built-in method setter of property object at 0x10ff07940>
>>> property().deleter
<built-in method deleter of property object at 0x10ff07998>

මෙම සැරසිළි ලෙස ක්රියා . ඔවුන් නව දේපල වස්තුවක් ආපසු ලබා දෙයි:

>>> property().getter(None)
<property object at 0x10ff079f0>

එය පැරණි වස්තුවක පිටපතකි, නමුත් එක් ශ්‍රිතයක් ප්‍රතිස්ථාපනය කර ඇත.

මතක තබා ගන්න, @decoratorසින්ටැක්ස් යනු සින්ටැක්ටික් සීනි පමණක් බව; වාක්‍ය ඛණ්ඩය:

@property
def foo(self): return self._foo

ඇත්තටම අදහස් කරන්නේ එකම දෙයයි

def foo(self): return self._foo
foo = property(foo)

එබැවින් fooශ්‍රිතය ප්‍රතිස්ථාපනය වේ property(foo), අප ඉහත දුටු විශේෂ වස්තුවකි. ඔබ භාවිතා කරන විට @foo.setter(), ඔබ කරන්නේ property().setterමා ඉහත පෙන්වූ ක්‍රමයට අමතන්න , එය දේපලෙහි නව පිටපතක් ලබා දෙයි, නමුත් මේ වතාවේ සැකසුම් ශ්‍රිතය වෙනුවට අලංකාර ක්‍රමය වෙනුවට ආදේශ කර ඇත.

පහත දැක්වෙන අනුපිළිවෙල මඟින් එම සැරසිලි ක්‍රම භාවිතා කරමින් පූර්ණ දේපලක් නිර්මාණය කරයි.

පළමුවෙන්ම අපි යම් කාර්යයන් සහ propertyවස්තුවක් හුදෙක් ලබා ගන්නෙකු සමඟ නිර්මාණය කරමු :

>>> def getter(self): print('Get!')
... 
>>> def setter(self, value): print('Set to {!r}!'.format(value))
... 
>>> def deleter(self): print('Delete!')
... 
>>> prop = property(getter)
>>> prop.fget is getter
True
>>> prop.fset is None
True
>>> prop.fdel is None
True

ඊළඟට අපි .setter()ක්‍රමයක් භාවිතා කරන්නේ කට්ටලයක් එකතු කිරීමට ය:

>>> prop = prop.setter(setter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is None
True

අවසාන වශයෙන් අපි .deleter()ක්‍රමය සමඟ මකාදැමීමක් එකතු කරමු :

>>> prop = prop.deleter(deleter)
>>> prop.fget is getter
True
>>> prop.fset is setter
True
>>> prop.fdel is deleter
True

පසුගිය නමුත් අවම වශයෙන් නොව, propertyවස්තුව ලෙස ක්රියා descriptor වස්තුව එය එසේ, .__get__(), .__set__()හා .__delete__()උදාහරණයක් බලමු ඩේටා ලබා, සැකසීම සහ මකා දැමීම බවට කිව ක්රම:

>>> class Foo: pass
... 
>>> prop.__get__(Foo(), Foo)
Get!
>>> prop.__set__(Foo(), 'bar')
Set to 'bar'!
>>> prop.__delete__(Foo())
Delete!

විස්තරය හොව්ටෝට පිරිසිදු පයිතන් නියැදි ක්‍රියාත්මක කිරීම ඇතුළත් වේ property():

class Property:
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError("unreadable attribute")
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError("can't set attribute")
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError("can't delete attribute")
        self.fdel(obj)

    def getter(self, fget):
        return type(self)(fget, self.fset, self.fdel, self.__doc__)

    def setter(self, fset):
        return type(self)(self.fget, fset, self.fdel, self.__doc__)

    def deleter(self, fdel):
        return type(self)(self.fget, self.fset, fdel, self.__doc__)

11
ඉතා හොඳයි. අපේක්ෂිත ප්‍රති with ල සමඟ Foo.prop = propඔබට කළ හැකි බව ඔබට එකතු කළ හැකිය Foo().prop = 5; pront Foo().prop; del Foo().prop.
glglgl

13
ක්රමය වස්තූන් පියාසර තහනම් මත නිර්මාණය කිරීම සහ හැකි ලබා ගත හැකි නම්, එම මතකය ස්ථානය නැවත භාවිත.
මාර්ටිජ් පීටර්ස්

1
Ark මාකස් මෙස්කානන්: මම භාවිතා type()කරන්නේ ඩන්ඩර් ගුණාංග හා ක්‍රමවේදයන් වෙත ප්‍රවේශ වීම සඳහා වන අතර එය සම්මත කාර්යයන් සහ ක්‍රියාකරුවන් විසින් විස්තාරණ ස්ථාන ලෙස භාවිතා කිරීමට අදහස් කරයි.
මාර්ටිජන් පීටර්ස්

2
Ark මාකස් මෙස්කානන්: වස්තුව වෙනස් කළ නොහැකි නිසාත්, ඔබ එය විකෘති කළහොත් ඔබට එය උප පංතියක විශේෂීකරණය කළ නොහැකි නිසාත් ය.
මාර්ටිජ් පීටර්ස්

5
Ark මාකස් මෙස්කානන්: සැකසුම් රහිතව පයිතන් අභිබවා යන අය බලන්න ; අළුත් දෙයක් නැවත ලබා දීමට වඩා ස්ථානයෙහි වස්තුව @human.name.getterවෙනස් කළ හොත්, එම propertyසුපිරි human.nameපන්තියේ හැසිරීම වෙනස් කරමින් ගුණාංගය වෙනස් වේ.
මාර්ටිජ් පීටර්ස්

211

ප්‍රලේඛනය පවසන්නේ එය කියවිය හැකි ගුණාංග නිර්මාණය කිරීම සඳහා වූ කෙටිමඟක් පමණක් බවයි. නිසා

@property
def x(self):
    return self._x

සමාන වේ

def getx(self):
    return self._x
x = property(getx)

22
සම්පුර්ණ සන්දර්භය (වඩාත්ම ඉහළ නංවන ලද පිළිතුර) හොඳයි, නමුත් මෙම පිළිතුර වෙනත් අයෙකු @propertyතම පන්තියේ සැරසිලි කරුවෙකු ලෙස භාවිතා කළේ ඇයිදැයි සොයා බැලීමට ප්‍රායෝගිකව ප්‍රයෝජනවත් විය .
ijoseph

1
ඔබට පන්තියකට ගුණාංගයක් එක් කිරීමට අවශ්‍ය වූ විටත්, එම පන්තියේ කලින් නිර්මාණය කරන ලද වස්තූන් සමඟ අනුකූලතාව පවත්වා ගැනීමටත් අවශ්‍ය වන විට (උදා: අච්චාරු ගොනුවක සුරැකිය හැක).
ඇන්ඩි

මම සිතන්නේ ප්‍රලේඛනයේ වැදගත්ම කොටස (අවම වශයෙන්, ඕනෑම අයෙකු දේපල භාවිතා කරන්නේ ඇයිද යන්න මට වඩාත්ම තේරුම් ගැනීමට උපකාරවත් වූයේ): “c යනු C හි නිදසුනක් නම්, cx ලබා ගන්නා තැනැත්තාට ආයාචනා කරනු ඇත, cx = අගය සැකසුම්කරුට ආයාචනා කරයි සහ ඩෙල් සීඑක්ස් මකන්න. ”
getup8

116

@propertyක්‍රියාත්මක කළ හැකි ආකාරය පිළිබඳ අවම උදාහරණයක් මෙන්න :

class Thing:
    def __init__(self, my_word):
        self._word = my_word 
    @property
    def word(self):
        return self._word

>>> print( Thing('ok').word )
'ok'

එසේ නොමැතිනම් wordදේපලක් වෙනුවට ක්‍රමයක් ලෙස පවතී.

class Thing:
    def __init__(self, my_word):
        self._word = my_word
    def word(self):
        return self._word

>>> print( Thing('ok').word() )
'ok'

1
() ශ්‍රිතය / දේපල යන වචනය init හි අර්ථ දැක්වීමට අවශ්‍ය නම් මෙම උදාහරණය පෙනෙන්නේ කෙසේද?
ජේ ජේ

6
මම සහිත වෙනුවට, මෙහි දේපල decorator නිර්මාණය වෙනවා ඇයි හැකි කෙනෙකු පැහැදිලි කරුණාකර self.word = my_wordපසුව එම මාර්ගය වැඩ කරන, -print( Thing('ok').word ) = 'ok'
SilverSlash

1
IlSilverSlash මෙය සරල උදාහරණයකි, සැබෑ භාවිත නඩුවකට වඩාත් සංකීර්ණ ක්‍රමයක් ඇතුළත් වේ
ඇලෙක්ස්

කරුණාකර මට පැහැදිලි කළ හැකිද, මුද්‍රණ යන්ත්‍රය Thing('ok').wordක්‍රියාකාරී වේලාවේදී අභ්‍යන්තරව ක්‍රියා කරන්නේ කෙසේද?
වික්‍රොබොට්

84

පළමු කොටස සරලයි:

@property
def x(self): ...

සමාන වේ

def x(self): ...
x = property(x)
  • එය propertyහුදෙක් ලබා ගන්නෙකු සමඟ නිර්මාණය කිරීම සඳහා සරල කරන ලද වාක්‍ය ඛණ්ඩයකි.

ඊළඟ පියවර වනුයේ මෙම දේපල සැකසුම්කරුවෙකු සහ මකාදැමීමකින් දීර් extend කිරීමයි. සුදුසු ක්‍රමවේදයන් සමඟ මෙය සිදු වේ:

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

පැරණි දේ xසහ ලබා දී ඇති කට්ටලයෙන් සියල්ල උරුම කර ගන්නා නව දේපලක් ආපසු ලබා දේ.

x.deleter එකම ආකාරයකින් ක්‍රියා කරයි.


53

මෙය පහත දැක්වේ:

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

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

    @x.deleter
    def x(self):
        del self._x

සමාන වේ:

class C(object):
    def __init__(self):
        self._x = None

    def _x_get(self):
        return self._x

    def _x_set(self, value):
        self._x = value

    def _x_del(self):
        del self._x

    x = property(_x_get, _x_set, _x_del, 
                    "I'm the 'x' property.")

සමාන වේ:

class C(object):
    def __init__(self):
        self._x = None

    def _x_get(self):
        return self._x

    def _x_set(self, value):
        self._x = value

    def _x_del(self):
        del self._x

    x = property(_x_get, doc="I'm the 'x' property.")
    x = x.setter(_x_set)
    x = x.deleter(_x_del)

සමාන වේ:

class C(object):
    def __init__(self):
        self._x = None

    def _x_get(self):
        return self._x
    x = property(_x_get, doc="I'm the 'x' property.")

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

    def _x_del(self):
        del self._x
    x = x.deleter(_x_del)

සමාන වන්නේ:

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

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

    @x.deleter
    def x(self):
        del self._x

4
පළමු සහ අවසාන කේත උදාහරණ සමාන වේ (වාචික).
ඇඩෝමාස් බලියුකා

2
මම හිතන්නේ එය හිතාමතාම. කෙසේ හෝ වේවා, මෙය මට වඩාත්ම ප්‍රයෝජනවත් උදාහරණය වූයේ මෙම උදාහරණ වලින් මට අර්ථය ලබා ගත හැකි බැවිනි. ස්තූතියි ill බිල් මුවර්
ජෙරමි

52

මෙතැනින්@property ලබාගත් ප්‍රතික්‍රියාකාරක කේතයක් යමෙකුට ලබා ගත හැකි විට උපකාර කළ හැකි ආකාරය පිළිබඳ තවත් උදාහරණයක් පහත දැක්වේ (මම එය පහත සාරාංශගත කරමි):

ඔබ Moneyමේ වගේ පන්තියක් නිර්මාණය කළා යැයි සිතන්න :

class Money:
    def __init__(self, dollars, cents):
        self.dollars = dollars
        self.cents = cents

පරිශීලකයෙකු ඔහු / ඇය භාවිතා කරන මෙම පන්තිය අනුව පුස්තකාලයක් නිර්මාණය කරයි

money = Money(27, 12)

print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 27 dollar and 12 cents.

දැන් අපි ඔබේ Moneyපංතිය වෙනස් කර ගුණාංග dollarsසහ centsගුණාංග ඉවත් කිරීමට තීරණය කළෙමු යැයි සිතමු. ඒ වෙනුවට මුළු ශත ප්‍රමාණය පමණක් නිරීක්ෂණය කිරීමට තීරණය කරමු:

class Money:
    def __init__(self, dollars, cents):
        self.total_cents = dollars * 100 + cents

ඉහත සඳහන් කළ පරිශීලකයා දැන් ඔහුගේ / ඇයගේ පුස්තකාලය පෙර මෙන් ක්‍රියාත්මක කිරීමට උත්සාහ කරන්නේ නම්

money = Money(27, 12)

print("I have {} dollar and {} cents.".format(money.dollars, money.cents))

එය දෝෂයක් වනු ඇත

AttributeError: 'මුදල්' වස්තුවට 'ඩොලර්' ගුණාංගයක් නොමැත

දැන් ඔබේ මුල් පරිහරණය කරන බවත් සෑම දෙනාට මාධ්යයන් Moneyපන්ති එහිදී කේතය සියලු මාර්ග වෙනස් කිරීමට සිදුව තිබේ dollarsහා centsඉතා වේදනාකාරී විය හැකි භාවිතා ... ඒ නිසා, කෙසේ ද මේ මඟ හැරිය හැක්කේ කෙසේද? භාවිතා කිරීමෙන් @property!

එය කෙසේද:

class Money:
    def __init__(self, dollars, cents):
        self.total_cents = dollars * 100 + cents

    # Getter and setter for dollars...
    @property
    def dollars(self):
        return self.total_cents // 100

    @dollars.setter
    def dollars(self, new_dollars):
        self.total_cents = 100 * new_dollars + self.cents

    # And the getter and setter for cents.
    @property
    def cents(self):
        return self.total_cents % 100

    @cents.setter
    def cents(self, new_cents):
        self.total_cents = 100 * self.dollars + new_cents

අපි දැන් අපේ පුස්තකාලයෙන් කතා කරන විට

money = Money(27, 12)

print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 27 dollar and 12 cents.

එය අපේක්ෂා කළ පරිදි ක්‍රියාත්මක වන අතර අපගේ පුස්තකාලයේ එක් කේත පේළියක් වෙනස් කිරීමට අපට අවශ්‍ය නොවීය! ඇත්ත වශයෙන්ම, අප යැපෙන පුස්තකාලය වෙනස් වී ඇති බව දැන ගැනීමට පවා අපට අවශ්‍ය නොවනු ඇත.

එසේම setterවැඩ හොඳින් වේ:

money.dollars += 2
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 29 dollar and 12 cents.

money.cents += 10
print("I have {} dollar and {} cents.".format(money.dollars, money.cents))
# prints I have 29 dollar and 22 cents.

ඔබට @propertyවියුක්ත පන්තිවලද භාවිතා කළ හැකිය ; මම මෙහි අවම උදාහරණයක් දෙන්නෙමි .


ඔබේ සාරාංශය ඉතා හොඳයි, වෙබ් අඩවිය ගන්නා උදාහරණය ටිකක් අමුතුයි .. ආරම්භකයකු අසයි .. ඇයි අපට එයට ඇලී සිටිය නොහැක්කේ self.dollar = dollars? අපි ropproperty සමඟ බොහෝ දේ කර ඇත, නමුත් නිස්සාරණ ක්‍රියාකාරිත්වයක් එකතු වී නැති බව පෙනේ.
ෂෙන්ග් බී

2
He ෂෙන්ග්බි: සැබෑ උදාහරණය කෙරෙහි එතරම් අවධානය යොමු නොකරන්න, නමුත් යටින් පවතින මූලධර්මය කෙරෙහි වැඩි අවධානයක් යොමු නොකරන්න: - කුමන හේතුවක් නිසා හෝ - ඔබට ප්‍රතික්‍රියාකාරක කේතය කළ යුතු නම්, වෙනත් කෙනෙකුගේ කේතයකට බලපෑමක් නොකර ඔබට එය කළ හැකිය.
ක්ලෙබ්

21

මම මෙහි ඇති සියලුම ලිපි කියවා අපට සැබෑ ජීවිත ආදර්ශයක් අවශ්‍ය බව තේරුම් ගතිමි. ඇත්ත වශයෙන්ම, අපට rop ලදායිතාව ඇත්තේ ඇයි? එබැවින්, ඔබ සත්‍යාපන පද්ධතිය භාවිතා කරන Flask යෙදුමක් සලකා බලන්න. ඔබ ආදර්ශ පරිශීලකයෙකු ලෙස ප්‍රකාශ කරන්නේ models.py:

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True, index=True)
    username = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))

    ...

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

මෙම කේතය තුළ අපි "සැඟවුණු" ගුණාංගය passwordභාවිතා කරන්නේ ඔබ එය කෙලින්ම ප්‍රවේශ කිරීමට උත්සාහ කරන විට @propertyඑය අවුලුවන AttributeErrorඅතර සත්‍ය සිද්ධි විචල්‍යය සැකසීමට අපි @ property.setter භාවිතා කළෙමු password_hash.

දැන් auth/views.pyඅපට පරිශීලකයෙකු සමඟ මෙය ස්ථාපනය කළ හැකිය:

...
@auth.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        user = User(email=form.email.data,
                    username=form.username.data,
                    password=form.password.data)
        db.session.add(user)
        db.session.commit()
...

passwordපරිශීලකයෙකු පෝරමය පුරවන විට ලියාපදිංචි කිරීමේ පෝරමයකින් ලැබෙන ගුණාංගය සැලකිල්ලට ගන්න. මුරපදය තහවුරු කිරීම ඉදිරිපස කෙළවරේ සිදු වේ EqualTo('password', message='Passwords must match')(ඔබ පුදුම වන්නේ නම්, නමුත් එය වෙනස් මාතෘකාවක් හා සම්බන්ධ ෆ්ලැස්ක් ආකෘති).

මෙම උදාහරණය ප්‍රයෝජනවත් වනු ඇතැයි මම බලාපොරොත්තු වෙමි


20

පයිතන් සැරසිලි කරුවන් සමඟ ආරම්භ කරමු.

පයිතන් සැරසිලි කරුවෙකු යනු දැනටමත් අර්ථ දක්වා ඇති ශ්‍රිතයකට අමතර ක්‍රියාකාරීත්වයන් කිහිපයක් එකතු කිරීමට උපකාරී වන ශ්‍රිතයකි.

පයිතන්හි සෑම දෙයක්ම වස්තුවකි. පයිතන් හි කාර්යයන් පළමු පන්තියේ වස්තූන් වන අතර එයින් අදහස් කරන්නේ ඒවා විචල්‍යයකින් යොමු කළ හැකි බවත්, ලැයිස්තු වලට එකතු කළ හැකි බවත්, වෙනත් ශ්‍රිතයක් සඳහා තර්ක ලෙස සම්මත කළ හැකි බවත් ය.

පහත කේත ස්නිපටය සලකා බලන්න.

def decorator_func(fun):
    def wrapper_func():
        print("Wrapper function started")
        fun()
        print("Given function decorated")
        # Wrapper function add something to the passed function and decorator 
        # returns the wrapper function
    return wrapper_func

def say_bye():
    print("bye!!")

say_bye = decorator_func(say_bye)
say_bye()

# Output:
#  Wrapper function started
#  bye
#  Given function decorated

මෙහිදී අපට කිව හැක්කේ සැරසිලි ශ්‍රිතය අපගේ say_hello ශ්‍රිතය වෙනස් කර එහි අමතර කේත පේළි කිහිපයක් එක් කළ බවයි.

සැරසිලි සඳහා පයිතන් සින්ටැක්ස්

def decorator_func(fun):
    def wrapper_func():
        print("Wrapper function started")
        fun()
        print("Given function decorated")
        # Wrapper function add something to the passed function and decorator 
        # returns the wrapper function
    return wrapper_func

@decorator_func
def say_bye():
    print("bye!!")

say_bye()

සිද්ධි සිද්ධියකට වඩා සියල්ල නිගමනය කරමු, නමුත් ඊට පෙර අපි සමහර ඕප් ප්‍රින්සිපල් ගැන කතා කරමු.

දත්ත සංවර්‍ධනය කිරීමේ මූලධර්මය සහතික කිරීම සඳහා බොහෝ වස්තු දිශානත ක්‍රමලේඛන භාෂාවල භාවිතා කරන්නන් සහ සැකසුම් භාවිතා කරනු ලැබේ (මෙම දත්ත මත ක්‍රියාත්මක වන ක්‍රම සමඟ දත්ත එකතු කිරීම ලෙස සැලකේ.)

මෙම ක්‍රම ඇත්ත වශයෙන්ම දත්ත ලබා ගැනීම සඳහා ලබා ගන්නා තැනැත්තා සහ දත්ත වෙනස් කිරීම සඳහා වන සැකසුම වේ.

මෙම මූලධර්මයට අනුව, පන්තියක ගුණාංග වෙනත් කේත වලින් සැඟවීමට සහ ආරක්ෂා කිරීමට පුද්ගලික කර ඇත.

ඔව්, rop ප්‍රොපර්ටි යනු මූලික වශයෙන් ගෙටර්ස් සහ සෙටර් භාවිතා කිරීමට පයිතොනික් ක්‍රමයකි.

පයිතන්ට දේපල නමින් විශිෂ්ට සංකල්පයක් ඇති අතර එමඟින් වස්තු-නැඹුරු ක්‍රමලේඛකයෙකුගේ ජීවිතය වඩාත් සරල කරයි.

සෙල්සියස් අංශක උෂ්ණත්වය ගබඩා කළ හැකි පන්තියක් සෑදීමට ඔබ තීරණය කළ බව අපි උපකල්පනය කරමු.

class Celsius:
def __init__(self, temperature = 0):
    self.set_temperature(temperature)

def to_fahrenheit(self):
    return (self.get_temperature() * 1.8) + 32

def get_temperature(self):
    return self._temperature

def set_temperature(self, value):
    if value < -273:
        raise ValueError("Temperature below -273 is not possible")
    self._temperature = value

ප්‍රතිනිර්මාණය කළ කේතය, දේපල සමඟ අපට එය සාක්ෂාත් කරගත හැකි ආකාරය මෙන්න.

පයිතන්හිදී, දේපල () යනු දේපල වස්තුවක් නිර්මාණය කර ආපසු ලබා දෙන ගොඩනංවන ලද ශ්‍රිතයකි.

දේපල වස්තුවකට ක්‍රම තුනක් ඇත, getter (), setter () සහ delete ().

class Celsius:
def __init__(self, temperature = 0):
    self.temperature = temperature

def to_fahrenheit(self):
    return (self.temperature * 1.8) + 32

def get_temperature(self):
    print("Getting value")
    return self.temperature

def set_temperature(self, value):
    if value < -273:
        raise ValueError("Temperature below -273 is not possible")
    print("Setting value")
    self.temperature = value

temperature = property(get_temperature,set_temperature)

මෙහි,

temperature = property(get_temperature,set_temperature)

බිඳ දැමිය හැකිය,

# make empty property
temperature = property()
# assign fget
temperature = temperature.getter(get_temperature)
# assign fset
temperature = temperature.setter(set_temperature)

සැලකිල්ලට ගත යුතු කරුණ:

  • get_temperature ක්‍රමයක් වෙනුවට දේපලක් ලෙස පවතී.

දැන් ඔබට ලිවීමෙන් උෂ්ණත්වයේ වටිනාකමට ප්‍රවේශ විය හැකිය.

C = Celsius()
C.temperature
# instead of writing C.get_temperature()

Get_temperature සහ set_temperature නම් අනවශ්‍ය බැවින් අපට තවදුරටත් ඉදිරියට යා හැකි අතර පන්ති නාම අවකාශය දූෂණය කරයි.

මෙම pythonic මාර්ගය ඉහත සඳහන් ගැටළුවට සමග ගනුදෙනු කිරීමට භාවිතා කිරීමයි @property .

class Celsius:
    def __init__(self, temperature = 0):
        self.temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

    @property
    def temperature(self):
        print("Getting value")
        return self.temperature

    @temperature.setter
    def temperature(self, value):
        if value < -273:
            raise ValueError("Temperature below -273 is not possible")
        print("Setting value")
        self.temperature = value

සැලකිල්ලට ගත යුතු කරුණු -

  1. වටිනාකමක් ලබා ගැනීම සඳහා භාවිතා කරන ක්‍රමයක් "ropproperty" වලින් සරසා ඇත.
  2. කට්ටලය ලෙස ක්‍රියා කළ යුතු ක්‍රමය "@ temperature.setter" වලින් සරසා ඇත, ශ්‍රිතය "x" ලෙස නම් කර තිබුනේ නම්, අපට එය "@ x.setter" වලින් සරසා ගත යුතුය.
  3. අපි එකම නමක් සහිත "ක්‍රම දෙකක්" සහ වෙනස් පරාමිතීන් "ඩෙෆ් උෂ්ණත්වය (ස්වයං)" සහ "ඩෙෆ් උෂ්ණත්වය (ස්වයං, x)" ලිව්වෙමු.

ඔබට පෙනෙන පරිදි, කේතය අනිවාර්යයෙන්ම අඩු අලංකාර වේ.

දැන් අපි එක් සැබෑ ජීවිතයේ ප්‍රායෝගික දර්ශනයක් ගැන කතා කරමු.

ඔබ පහත පරිදි පන්තියක් නිර්මාණය කර ඇති බව කියමු:

class OurClass:

    def __init__(self, a):
        self.x = a


y = OurClass(10)
print(y.x)

දැන්, අපගේ පංතිය සේවාදායකයින් අතර ජනප්‍රිය වී ඇති බවත්, ඔවුන් එය ඔවුන්ගේ වැඩසටහන් වලදී භාවිතා කිරීමට පටන් ගත් බවත්, ඔවුන් වස්තුව සඳහා සියලු ආකාරයේ පැවරුම් කළ බවත් අපි තවදුරටත් උපකල්පනය කරමු.

එක් අවාසනාවන්ත දවසක, විශ්වාසදායක සේවාදායකයෙක් අප වෙත පැමිණ "x" අගය 0 ත් 1000 ත් අතර අගයක් විය යුතු යැයි යෝජනා කළේය, මෙය සැබවින්ම භයානක අවස්ථාවකි!

ගුණාංග නිසා එය පහසු ය: අපි "x" හි දේපල අනුවාදයක් නිර්මාණය කරමු.

class OurClass:

    def __init__(self,x):
        self.x = x

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self, x):
        if x < 0:
            self.__x = 0
        elif x > 1000:
            self.__x = 1000
        else:
            self.__x = x

මෙය විශිෂ්ටයි, එසේ නොවේ: ඔබට සිතාගත හැකි සරලම ක්‍රියාත්මක කිරීම සමඟ ආරම්භ කළ හැකි අතර, අතුරු මුහුණත වෙනස් නොකර දේපල අනුවාදයකට පසුව සංක්‍රමණය වීමට ඔබට නිදහස තිබේ! එබැවින් දේපල යනු ලබා ගන්නන් සහ සැකසුම්කරුවන් සඳහා ආදේශකයක් පමණක් නොවේ!

ඔබට මෙම ක්‍රියාත්මක කිරීම මෙතැනින් පරීක්ෂා කළ හැකිය


2
ඔබගේ සෙල්සියස් පන්තිය සැකසීමේදී අසීමිත ලෙස පසුබසිනු ඇත (එයින් අදහස් වන්නේ ක්ෂණිකව).
ටෙඩ් පෙට්‍රෝ

1
Ed ටෙඩ් පෙට්‍රෝ මම ඔබව ලබා ගත්තේ නැද්ද? සැකසීමේදී එය අසීමිත ලෙස ප්‍රතිපෝෂණය වන්නේ කෙසේද?
දිව්‍යංෂු රාවට්

මෙය සැබවින්ම පැහැදිලි නැත ... මිනිසුන් අසන්නේ ඇයිදැයි විමසයි, නමුත් උදාහරණය ඒත්තු ගැන්වෙන්නේ නැත ...
ෂෙන්ග් බී

1
එය මගේ පෞද්ගලික මතයයි. ඔබේ පිළිතුර ඇත්තෙන්ම හොඳ විය හැකිය. එබැවින් එය අත්හරින්න.
ෂෙන්ග් බී

1
ඉහළම ඡන්දය දුන් පිළිතුරු හා සසඳන විට, මෙය මිනිසුන් සඳහා නිර්මාණය කර ඇත; ස්තූතියි.
Info5ek

18

මෙම කරුණ එහි සිටින බොහෝ අය විසින් නිෂ්කාශනය කර ඇත, නමුත් මෙන්න මම සෙවූ point ජු කරුණකි. @ ප්‍රොපර්ටි සැරසිලි කරුවෙකු සමඟ ආරම්භ කිරීම වැදගත් යැයි මට හැඟෙන්නේ මෙයයි. උදා: - -

class UtilityMixin():
    @property
    def get_config(self):
        return "This is property"

"Get_config ()" ශ්‍රිතය කැඳවීම මේ ආකාරයට ක්‍රියා කරයි.

util = UtilityMixin()
print(util.get_config)

ශ්‍රිතය ඇමතීම සඳහා මම "()" වරහන් භාවිතා කර නොමැති බව ඔබ දුටුවහොත්. මම rop ප්‍රොපර්ටි සැරසිලි කරුවෙකු සොයමින් සිටි මූලික දෙය මෙයයි. එවිට ඔබට ඔබේ ශ්‍රිතය විචල්‍යයක් මෙන් භාවිතා කළ හැකිය.


6

property@propertyසැරසිලි කරුවා පිටුපස පන්තියකි .

ඔබට සැමවිටම මෙය පරීක්ෂා කළ හැකිය:

print(property) #<class 'property'>

වාක්‍ය ඛණ්ඩය help(property)පෙන්වීමට මම උදාහරණය නැවත ලිව්වෙමි@property

class C:
    def __init__(self):
        self._x=None

    @property 
    def x(self):
        return self._x

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

    @x.deleter
    def x(self):
        del self._x

c = C()
c.x="a"
print(c.x)

property()සින්ටැක්ස් වලට ක්‍රියාකාරීව සමාන වේ :

class C:
    def __init__(self):
        self._x=None

    def g(self):
        return self._x

    def s(self, v):
        self._x = v

    def d(self):
        del self._x

    prop = property(g,s,d)

c = C()
c.x="a"
print(c.x)

ඔබට පෙනෙන පරිදි අපි දේපල භාවිතා කරන ආකාරයෙහි වෙනසක් නැත.

ප්‍රශ්න @propertyසැරසිලි කරන්නාට පිළිතුරු සැපයීම propertyපන්තිය හරහා ක්‍රියාත්මක වේ.


ඉතින්, ප්රශ්නය වන්නේ propertyපන්තිය ටිකක් පැහැදිලි කිරීමයි . මෙම රේඛාව:

prop = property(g,s,d)

ආරම්භය විය. අපට එය නැවත ලිවිය හැකිය:

prop = property(fget=g,fset=s,fdel=d)

අර්ථය fget, fsetසහ fdel:

 |    fget
 |      function to be used for getting an attribute value
 |    fset
 |      function to be used for setting an attribute value
 |    fdel
 |      function to be used for del'ing an attribute
 |    doc
 |      docstring

ඊළඟ රූපයේ දැක්වෙන්නේ පන්තියේ සිට අප සතුව ඇති ත්‍රිත්වයයි property:

රූප විස්තරය මෙහි ඇතුළත් කරන්න

__get__,, __set__සහ අභිබවා__delete__ යා යුතුය . පයිතන් හි විස්තර කිරීමේ රටාව ක්‍රියාත්මක කිරීම මෙයයි.

පොදුවේ ගත් කල, විස්තර කරන්නා යනු “බන්ධන හැසිරීම” සහිත වස්තු ගුණාංගයකි, විස්තර කිරීමේ ප්‍රොටෝකෝලයෙහි ක්‍රම මගින් ගුණාංග ප්‍රවේශය ඉක්මවා ගොස් ඇත.

ඒ වගේම අපි දේපල භාවිතා කළ හැකිය setter, getterසහ deleterක්රම දේපළ උත්සවයට බැඳීමට. ඊළඟ උදාහරණය පරීක්ෂා කරන්න. s2පංතියේ ක්‍රමය මඟින් Cදේපල දෙගුණ වේ.

class C:
    def __init__(self):
        self._x=None

    def g(self):
        return self._x

    def s(self, x):
        self._x = x

    def d(self):
        del self._x

    def s2(self,x):
        self._x=x+x


    x=property(g)
    x=x.setter(s)
    x=x.deleter(d)      


c = C()
c.x="a"
print(c.x) # outputs "a"

C.x=property(C.g, C.s2)
C.x=C.x.deleter(C.d)
c2 = C()
c2.x="a"
print(c2.x) # outputs "aa"

3

හොඳම පැහැදිලි කිරීම මෙතැනින් සොයාගත හැකිය: පයිතන් rop සෞඛ්‍යය පැහැදිලි කිරීම - භාවිතා කරන්නේ කෙසේද සහ කවදාද? (සම්පූර්ණ උදාහරණ) සෙල්වා ප්‍රභාකරන් | Posted on නොවැම්බර් 5, 2018

එය කෙසේ දැයි තේරුම් ගැනීමට එය මට උදව් විය.

https://www.machinelearningplus.com/python/python-property/


1

දේපලක් ආකාර දෙකකින් ප්රකාශ කළ හැකිය.

  • ගුණාංගයක් සඳහා ගැටුම්, සැකසුම් ක්‍රම නිර්මාණය කිරීම සහ ඒවා දේපල ක්‍රියාකාරිත්වයට තර්කයක් ලෙස සම්මත කිරීම
  • @ ප්‍රොපර්ටි සැරසිලි යන්ත්‍රය භාවිතා කිරීම .

පයිතන්හි ඇති ගුණාංග ගැන මා ලියා ඇති උදාහරණ කිහිපයක් ඔබට දැක ගත හැකිය .


දේපල පංතියක් යැයි පවසමින් ඔබේ පිළිතුර යාවත්කාලීන කළ හැකිද?
prosti

0

මෙන්න තවත් උදාහරණයක්:

##
## Python Properties Example
##
class GetterSetterExample( object ):
    ## Set the default value for x ( we reference it using self.x, set a value using self.x = value )
    __x = None


##
## On Class Initialization - do something... if we want..
##
def __init__( self ):
    ## Set a value to __x through the getter / setter... Since __x is defined above, this doesn't need to be set...
    self.x = 1234

    return None


##
## Define x as a property, ie a getter - All getters should have a default value arg, so I added it - it will not be passed in when setting a value, so you need to set the default here so it will be used..
##
@property
def x( self, _default = None ):
    ## I added an optional default value argument as all getters should have this - set it to the default value you want to return...
    _value = ( self.__x, _default )[ self.__x == None ]

    ## Debugging - so you can see the order the calls are made...
    print( '[ Test Class ] Get x = ' + str( _value ) )

    ## Return the value - we are a getter afterall...
    return _value


##
## Define the setter function for x...
##
@x.setter
def x( self, _value = None ):
    ## Debugging - so you can see the order the calls are made...
    print( '[ Test Class ] Set x = ' + str( _value ) )

    ## This is to show the setter function works.... If the value is above 0, set it to a negative value... otherwise keep it as is ( 0 is the only non-negative number, it can't be negative or positive anyway )
    if ( _value > 0 ):
        self.__x = -_value
    else:
        self.__x = _value


##
## Define the deleter function for x...
##
@x.deleter
def x( self ):
    ## Unload the assignment / data for x
    if ( self.__x != None ):
        del self.__x


##
## To String / Output Function for the class - this will show the property value for each property we add...
##
def __str__( self ):
    ## Output the x property data...
    print( '[ x ] ' + str( self.x ) )


    ## Return a new line - technically we should return a string so it can be printed where we want it, instead of printed early if _data = str( C( ) ) is used....
    return '\n'

##
##
##
_test = GetterSetterExample( )
print( _test )

## For some reason the deleter isn't being called...
del _test.x

මූලික වශයෙන්, මම ඒ වෙනුවට x භාවිතා කරනවා හැර C (වස්තුව) උදාහරණයට සමාන වේ ... මම __init - ... හොඳයි .. මම ආරම්භ නොකරමි, නමුත් __x කොටස ලෙස අර්ථ දක්වා ඇති නිසා එය ඉවත් කළ හැකිය පන්තියේ ....

ප්‍රතිදානය:

[ Test Class ] Set x = 1234
[ Test Class ] Get x = -1234
[ x ] -1234

මම init හි self.x = 1234 ගැන අදහස් දක්වන්නේ නම් ප්‍රතිදානය:

[ Test Class ] Get x = None
[ x ] None

සහ මම _default = කිසිවක් _default = 0 ලෙස සකසන්නේ නම් (සියලු ලබා ගන්නන්ට පෙරනිමි අගයක් තිබිය යුතු නමුත් එය මා දුටු දෙයින් දේපල අගයන් මගින් සම්මත නොවන බැවින් ඔබට එය මෙහි අර්ථ දැක්විය හැකිය, සහ එය ඇත්ත වශයෙන්ම නරක නැත, මන්ද ඔබට පෙරනිමිය එක් වරක් නිර්වචනය කර එය සෑම තැනකම භාවිතා කළ හැකිය) එනම්: def x (self, _default = 0):

[ Test Class ] Get x = 0
[ x ] 0

සටහන: ලබා ගැනීමේ තර්කනය ඇත්තේ එය විසින් එය හසුරුවා ඇති බව සහතික කිරීම සඳහා එහි වටිනාකම හසුරුවා ගැනීම සඳහා පමණි - මුද්‍රණ ප්‍රකාශ සඳහාද එයම වේ ...

සටහන: මම ලුආට පුරුදු වී සිටින අතර, මම තනි ශ්‍රිතයක් අමතන විට 10+ සහායකයින් ගතිකව නිර්මාණය කිරීමට හැකි වන අතර මම ගුණාංග භාවිතා නොකර පයිතන් සඳහා සමාන දෙයක් සාදන ලද අතර එය යම් ප්‍රමාණයකට ක්‍රියා කරයි, නමුත්, පෙර කාර්යයන් නිර්මාණය වී තිබුණද භාවිතා කිරීම, නිර්මාණය කිරීමට පෙර ඒවා කැඳවීමේදී තවමත් ගැටළු ඇති අතර එය කේතනය කර නැති නිසා එය අමුතුයි ... මම කැමතියි ලුආ මෙටා-වගු වල නම්යශීලීභාවය සහ මට නියම කට්ටල / ලබා ගන්නන් භාවිතා කළ හැකිය අත්‍යවශ්‍යයෙන්ම සෘජුවම විචල්‍යයකට ප්‍රවේශ වීම වෙනුවට ... පයිතන් සමඟ සමහර දේවල් කෙතරම් ඉක්මණින් ගොඩනගා ගත හැකිදැයි මම කැමතියි - උදාහරණයක් ලෙස ගයි වැඩසටහන්. මම නිර්මාණය කරන එකක් අතිරේක පුස්තකාල නොමැතිව කළ නොහැකි වුවද - මම එය ඔටෝ හොට්කි හි කේත කළහොත් මට අවශ්‍ය ඩීඑල් ඇමතුම් වලට කෙලින්ම පිවිසිය හැකි අතර ජාවා, සී #, සී ++,

සටහන: මෙම සංසදයේ කේත ප්‍රතිදානය කැඩී ඇත - එය වැඩ කිරීම සඳහා කේතයේ පළමු කොටසට අවකාශය එක් කිරීමට මට සිදු විය - පිටපත් කිරීම / ඇලවීම මඟින් ඔබ සියලු අවකාශයන් ටැබ් බවට පරිවර්තනය කරන බව සහතික කළ විට .... මම පයිතන් සඳහා ටැබ් භාවිතා කරමි. පේළි 10,000 ක් වන ගොනුවක් අවකාශය සහිත 512KB සිට 1MB දක්වා සහ ටැබ් සහිත 100 සිට 200KB දක්වා විය හැකි අතර එය ගොනු විශාලත්වය සඳහා විශාල වෙනසකට සමාන වන අතර සැකසුම් කාලය අඩු කරයි ...

ටැබ් එක පරිශීලකයෙකුට සකස් කළ හැකිය - එබැවින් ඔබ ඉඩ 2 ක් පළල, 4, 8 හෝ ඔබට කළ හැකි ඕනෑම දෙයක් කැමති නම් එය ඇස් පෙනීමේ .නතා ඇති සංවර්ධකයින් සඳහා කල්පනාකාරී වේ.

සටහන: සංසදයේ මෘදුකාංගයේ ඇති දෝෂයක් හේතුවෙන් පන්තියේ අර්ථ දක්වා ඇති සියලුම කාර්යයන් නිසි ලෙස මුද්‍රණය නොකෙරේ - ඔබ පිටපත් / ඇලවූ විට එය ඇතුල් කරන බවට සහතික වන්න

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.