Python Language
कक्षाएं
खोज…
परिचय
पायथन न केवल एक लोकप्रिय स्क्रिप्टिंग भाषा के रूप में खुद को पेश करता है, बल्कि ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग प्रतिमान का भी समर्थन करता है। कक्षाएं डेटा का वर्णन करती हैं और उस डेटा को हेरफेर करने के तरीके प्रदान करती हैं, सभी एक ही वस्तु के तहत शामिल हैं। इसके अलावा, कक्षाएं डेटा के अमूर्त अभ्यावेदन से ठोस कार्यान्वयन विवरण को अलग करके अमूर्तता की अनुमति देती हैं।
कोड का उपयोग करने वाली कक्षाएं आमतौर पर पढ़ने, समझने और बनाए रखने में आसान होती हैं।
मूल वंशानुक्रम
पायथन में वंशानुक्रम जावा, सी ++ आदि जैसी अन्य वस्तु उन्मुख भाषाओं में उपयोग किए जाने वाले समान विचारों पर आधारित है। एक नया वर्ग मौजूदा वर्ग से निम्नानुसार प्राप्त किया जा सकता है।
class BaseClass(object):
pass
class DerivedClass(BaseClass):
pass
BaseClass
पहले से ही विद्यमान (पैरेंट) वर्ग है, और DerivedClass
नई (बच्चे) वर्ग कि inherits (या उपवर्ग) से जिम्मेदार बताते है BaseClass
। नोट : पायथन 2.2 के रूप में, सभी वर्ग स्पष्ट रूप से object
क्लास से विरासत में मिलते हैं , जो सभी प्रकारों के लिए बेस क्लास है।
हम नीचे दिए गए उदाहरण में एक मूल Rectangle
वर्ग को परिभाषित करते हैं, जो कि object
से अंतर्निहित है:
class Rectangle():
def __init__(self, w, h):
self.w = w
self.h = h
def area(self):
return self.w * self.h
def perimeter(self):
return 2 * (self.w + self.h)
Rectangle
वर्ग एक निर्णायक के लिए एक आधार वर्ग के रूप में इस्तेमाल किया जा सकता Square
के रूप में एक वर्ग आयत के एक विशेष मामला है, वर्ग।
class Square(Rectangle):
def __init__(self, s):
# call parent constructor, w and h are both s
super(Square, self).__init__(s, s)
self.s = s
Square
वर्ग स्वचालित रूप से Rectangle
वर्ग के साथ-साथ ऑब्जेक्ट क्लास की सभी विशेषताओं को प्राप्त करेगा। super()
का उपयोग Rectangle
वर्ग के __init__()
पद्धति को कॉल करने के लिए किया जाता है, अनिवार्य रूप से आधार वर्ग के किसी भी ओवरराइड विधि को कॉल करने के लिए। नोट : पायथन 3 में, super()
को तर्कों की आवश्यकता नहीं है।
व्युत्पन्न वर्ग की वस्तुएं अपने आधार वर्गों की विशेषताओं को एक्सेस और संशोधित कर सकती हैं:
r.area()
# Output: 12
r.perimeter()
# Output: 14
s.area()
# Output: 4
s.perimeter()
# Output: 8
अंतर्निहित कार्य जो विरासत के साथ काम करते हैं
issubclass(DerivedClass, BaseClass)
: रिटर्न True
, तो DerivedClass
का एक उपवर्ग है BaseClass
isinstance(s, Class)
: रिटर्न True
, तो रों का एक उदाहरण है Class
या के व्युत्पन्न वर्ग के किसी भी Class
# subclass check
issubclass(Square, Rectangle)
# Output: True
# instantiate
r = Rectangle(3, 4)
s = Square(2)
isinstance(r, Rectangle)
# Output: True
isinstance(r, Square)
# Output: False
# A rectangle is not a square
isinstance(s, Rectangle)
# Output: True
# A square is a rectangle
isinstance(s, Square)
# Output: True
वर्ग और उदाहरण चर
इंस्टेंस चर प्रत्येक उदाहरण के लिए अद्वितीय होते हैं, जबकि कक्षा चर सभी उदाहरणों द्वारा साझा किए जाते हैं।
class C:
x = 2 # class variable
def __init__(self, y):
self.y = y # instance variable
C.x
# 2
C.y
# AttributeError: type object 'C' has no attribute 'y'
c1 = C(3)
c1.x
# 2
c1.y
# 3
c2 = C(4)
c2.x
# 2
c2.y
# 4
इस वर्ग के उदाहरणों पर कक्षा चर को एक्सेस किया जा सकता है, लेकिन वर्ग विशेषता को असाइन करने से एक आवृत्ति चर पैदा होगा जो वर्ग चर को छाया देता है
c2.x = 4
c2.x
# 4
C.x
# 2
ध्यान दें कि इंस्टेंसेस से क्लास वेरिएबल को म्यूट करने से कुछ अप्रत्याशित परिणाम हो सकते हैं।
class D:
x = []
def __init__(self, item):
self.x.append(item) # note that this is not an assigment!
d1 = D(1)
d2 = D(2)
d1.x
# [1, 2]
d2.x
# [1, 2]
D.x
# [1, 2]
बाउंड, अनबाउंड और स्टैटिक तरीके
पायथन 3 में बाध्य और अनबाउंड तरीकों का विचार हटा दिया गया था। पायथन 3 में जब आप किसी वर्ग के भीतर एक विधि की घोषणा करते हैं, तो आप एक def
कीवर्ड का उपयोग कर रहे हैं, इस प्रकार एक फंक्शन ऑब्जेक्ट का निर्माण होता है। यह एक नियमित कार्य है, और आसपास का वर्ग इसके नामस्थान के रूप में काम करता है। निम्न उदाहरण में हम प्रणाली की घोषणा f
वर्ग के भीतर A
है, और यह एक समारोह हो जाता है Af
:
class A(object):
def f(self, x):
return 2 * x
A.f
# <function A.f at ...> (in Python 3.x)
पायथन 2 में व्यवहार भिन्न था: वर्ग के भीतर फ़ंक्शन ऑब्जेक्ट्स को स्पष्ट रूप से टाइप instancemethod
की वस्तुओं के साथ बदल दिया गया था, जिन्हें अनबाउंड तरीके कहा जाता था क्योंकि वे किसी विशेष वर्ग के उदाहरण के लिए बाध्य नहीं थे। .__func__
संपत्ति का उपयोग करके अंतर्निहित फ़ंक्शन तक पहुंचना संभव था।
A.f
# <unbound method A.f> (in Python 2.x)
A.f.__class__
# <type 'instancemethod'>
A.f.__func__
# <function f at ...>
बाद के व्यवहारों को निरीक्षण द्वारा पुष्टि की जाती है - विधियों को पायथन 3 में कार्यों के रूप में मान्यता दी जाती है, जबकि पायथन 2 में भेद को बरकरार रखा जाता है।
import inspect
inspect.isfunction(A.f)
# True
inspect.ismethod(A.f)
# False
import inspect
inspect.isfunction(A.f)
# False
inspect.ismethod(A.f)
# True
पायथन फ़ंक्शन / विधि के दोनों संस्करणों में Af
को सीधे कहा जा सकता है, बशर्ते कि आप पहले तर्क के रूप में कक्षा A
का एक उदाहरण दें।
A.f(1, 7)
# Python 2: TypeError: unbound method f() must be called with
# A instance as first argument (got int instance instead)
# Python 3: 14
a = A()
A.f(a, 20)
# Python 2 & 3: 40
अब मान लीजिए कि a
वर्ग का एक उदाहरण है A
, क्या है af
तो? ठीक है, intuitively इस एक ही विधि का होना चाहिए f
वर्ग के A
, केवल यह किसी भी तरह "पता" चाहिए कि यह वस्तु के लिए लागू किया गया था a
- अजगर में इस विधि के लिए बाध्य कर कहा जाता है a
।
बुनियादी तथ्य विवरण इस प्रकार हैं: लेखन af
का आह्वान जादू __getattribute__
की विधि a
है, जो पहली जाँच करता है कि a
एक विशेषता नामक f
(यह नहीं है), तो चेक के वर्ग A
है कि क्या यह एक तरीका है इस तरह के एक नाम के साथ शामिल (यह है), और एक नई वस्तु बनाता m
प्रकार की method
जो मूल के संदर्भ में है Af
में m.__func__
, और वस्तु के लिए एक संदर्भ a
में m.__self__
। जब इस ऑब्जेक्ट को एक फ़ंक्शन के रूप में कहा जाता है, तो यह बस निम्नलिखित करता है: m(...) => m.__func__(m.__self__, ...)
। इस प्रकार इस वस्तु को एक बाध्य विधि कहा जाता है क्योंकि जब आह्वान किया जाता है तो वह उस वस्तु की आपूर्ति करना जानती है जो पहले तर्क के रूप में बंधी थी। (ये बातें पाइथन 2 और 3 में उसी तरह काम करती हैं)।
a = A()
a.f
# <bound method A.f of <__main__.A object at ...>>
a.f(2)
# 4
# Note: the bound method object a.f is recreated *every time* you call it:
a.f is a.f # False
# As a performance optimization you can store the bound method in the object's
# __dict__, in which case the method object will remain fixed:
a.f = a.f
a.f is a.f # True
अंत में, पायथन में वर्ग विधियाँ और स्थैतिक विधियाँ हैं - विशेष प्रकार की विधियाँ। क्लास मेथड्स रेगुलर मेथड्स की तरह ही काम करते हैं, सिवाय इसके कि जब किसी ऑब्जेक्ट पर इनवेस्ट किया जाता है तो वे ऑब्जेक्ट के बजाय ऑब्जेक्ट के क्लास से बंधते हैं। इस प्रकार m.__self__ = type(a)
। जब आप इस तरह के बाध्य विधि कॉल, यह वर्ग से गुजरता a
पहले तर्क के रूप में। स्टैटिक विधियां और भी सरल हैं: वे किसी भी चीज को बांधते नहीं हैं, और बस बिना किसी परिवर्तन के अंतर्निहित फ़ंक्शन को वापस करते हैं।
class D(object):
multiplier = 2
@classmethod
def f(cls, x):
return cls.multiplier * x
@staticmethod
def g(name):
print("Hello, %s" % name)
D.f
# <bound method type.f of <class '__main__.D'>>
D.f(12)
# 24
D.g
# <function D.g at ...>
D.g("world")
# Hello, world
ध्यान दें कि वर्ग विधियाँ वर्ग तक पहुँच जाने पर भी बाध्य होती हैं:
d = D()
d.multiplier = 1337
(D.multiplier, d.multiplier)
# (2, 1337)
d.f
# <bound method D.f of <class '__main__.D'>>
d.f(10)
# 20
यह ध्यान देने योग्य है कि सबसे निचले स्तर पर, फ़ंक्शन, विधियाँ, स्टेटमिथोड्स, आदि वास्तव में ऐसे डिस्क्रिप्टर हैं जो __get__
, __set
__ और वैकल्पिक रूप से __del__
विशेष विधियों का आह्वान करते हैं। Classmethods और staticmethods के बारे में अधिक जानकारी के लिए:
- पायथन में @staticmethod और @classmethod में क्या अंतर है?
- शुरुआती के लिए @classmethod और @staticmethod का मतलब?
नई शैली बनाम पुरानी शैली की कक्षाएं
कक्षाओं और प्रकारों को एकजुट करने के लिए पायथन 2.2 में नई शैली की कक्षाएं शुरू की गईं। उन्हें शीर्ष-स्तरीय object
प्रकार से विरासत में मिला है। एक नई शैली की कक्षा एक उपयोगकर्ता-परिभाषित प्रकार है , और बिल्ट-इन प्रकारों के समान है।
# new-style class
class New(object):
pass
# new-style instance
new = New()
new.__class__
# <class '__main__.New'>
type(new)
# <class '__main__.New'>
issubclass(New, object)
# True
पुरानी शैली की कक्षाएं object
से विरासत में नहीं मिलती हैं। पुरानी शैली के उदाहरण हमेशा अंतर्निहित instance
प्रकार के साथ कार्यान्वित किए जाते हैं।
# old-style class
class Old:
pass
# old-style instance
old = Old()
old.__class__
# <class __main__.Old at ...>
type(old)
# <type 'instance'>
issubclass(Old, object)
# False
पायथन 3 में, पुरानी शैली की कक्षाएं हटा दी गईं।
पायथन 3 में नई-शैली की कक्षाएं स्पष्ट रूप से object
से विरासत में मिली हैं, इसलिए अब MyClass(object)
को निर्दिष्ट करने की कोई आवश्यकता नहीं है।
class MyClass:
pass
my_inst = MyClass()
type(my_inst)
# <class '__main__.MyClass'>
my_inst.__class__
# <class '__main__.MyClass'>
issubclass(MyClass, object)
# True
उदाहरण चर के लिए डिफ़ॉल्ट मान
यदि चर में एक अपरिवर्तनीय प्रकार (जैसे एक स्ट्रिंग) का मान होता है, तो इस तरह एक डिफ़ॉल्ट मान निर्दिष्ट करना ठीक है
class Rectangle(object):
def __init__(self, width, height, color='blue'):
self.width = width
self.height = height
self.color = color
def area(self):
return self.width * self.height
# Create some instances of the class
default_rectangle = Rectangle(2, 3)
print(default_rectangle.color) # blue
red_rectangle = Rectangle(2, 3, 'red')
print(red_rectangle.color) # red
निर्माण में सूचियों जैसे उत्परिवर्तित वस्तुओं को आरम्भ करते समय सावधानी बरतने की आवश्यकता है। निम्नलिखित उदाहरण पर विचार करें:
class Rectangle2D(object):
def __init__(self, width, height, pos=[0,0], color='blue'):
self.width = width
self.height = height
self.pos = pos
self.color = color
r1 = Rectangle2D(5,3)
r2 = Rectangle2D(7,8)
r1.pos[0] = 4
r1.pos # [4, 0]
r2.pos # [4, 0] r2's pos has changed as well
यह व्यवहार इस तथ्य के कारण होता है कि पायथन डिफ़ॉल्ट पैरामीटर फ़ंक्शन निष्पादन में बाध्य हैं और फ़ंक्शन घोषणा में नहीं। डिफ़ॉल्ट आवृत्ति चर प्राप्त करने के लिए जिसे उदाहरणों के बीच साझा नहीं किया जाता है, किसी को इस तरह एक निर्माण का उपयोग करना चाहिए:
class Rectangle2D(object):
def __init__(self, width, height, pos=None, color='blue'):
self.width = width
self.height = height
self.pos = pos or [0, 0] # default value is [0, 0]
self.color = color
r1 = Rectangle2D(5,3)
r2 = Rectangle2D(7,8)
r1.pos[0] = 4
r1.pos # [4, 0]
r2.pos # [0, 0] r2's pos hasn't changed
म्यूटेबल डिफॉल्ट आर्ग्युमेंट्स और "लिस्ट एस्टनमेंट" और म्यूटेबल डिफॉल्ट आर्ग्युमेंट भी देखें ।
एकाधिक वंशानुक्रम
पायथन सी 3 रैखिककरण एल्गोरिथ्म का उपयोग उस क्रम को निर्धारित करने के लिए करता है जिसमें विधि सहित, वर्ग विशेषताओं को हल करना है। इसे विधि समाधान आदेश (MRO) के रूप में जाना जाता है।
यहाँ एक सरल उदाहरण है:
class Foo(object):
foo = 'attr foo of Foo'
class Bar(object):
foo = 'attr foo of Bar' # we won't see this.
bar = 'attr bar of Bar'
class FooBar(Foo, Bar):
foobar = 'attr foobar of FooBar'
अब अगर हम FooBar को तत्काल करते हैं, अगर हम foo विशेषता को देखते हैं, तो हम देखते हैं कि Foo की विशेषता पहले पाई गई है
fb = FooBar()
तथा
>>> fb.foo
'attr foo of Foo'
यहाँ FooBar का MRO है:
>>> FooBar.mro()
[<class '__main__.FooBar'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <type 'object'>]
यह बस कहा जा सकता है कि पायथन का एमआरओ एल्गोरिदम है
- जब तक गहराई पहले (जैसे
FooBar
फिरFoo
) - एक साझा माता-पिता (
object
) एक बच्चे (Bar
) और द्वारा अवरुद्ध है - कोई परिपत्र रिश्तों की अनुमति नहीं है।
उदाहरण के लिए, बार FooBar से वारिस नहीं हो सकता, जबकि FooBar बार से विरासत में मिलता है।
पायथन में एक व्यापक उदाहरण के लिए, विकिपीडिया प्रविष्टि देखें।
विरासत में एक और शक्तिशाली विशेषता super
। सुपर पैरेंट क्लासेस के फीचर्स ला सकता है।
class Foo(object):
def foo_method(self):
print "foo Method"
class Bar(object):
def bar_method(self):
print "bar Method"
class FooBar(Foo, Bar):
def foo_method(self):
super(FooBar, self).foo_method()
वर्ग की init पद्धति के साथ एकाधिक वंशानुक्रम, जब प्रत्येक वर्ग के पास init पद्धति होती है, तब हम कई ineritance के लिए प्रयास करते हैं, तब केवल init पद्धति को वर्ग कहा जाता है, जो पहले विरासत में मिली है।
उदाहरण के लिए केवल फू क्लास इनिट विधि जिसे बार क्लास इनिट कहा जाता है उसे नहीं बुलाया जाता है
class Foo(object):
def __init__(self):
print "foo init"
class Bar(object):
def __init__(self):
print "bar init"
class FooBar(Foo, Bar):
def __init__(self):
print "foobar init"
super(FooBar, self).__init__()
a = FooBar()
आउटपुट:
foobar init
foo init
लेकिन इसका मतलब यह नहीं है कि बार वर्ग विरासत में नहीं है। अंतिम फूबर वर्ग का उदाहरण भी बार वर्ग और फू वर्ग का उदाहरण है।
print isinstance(a,FooBar)
print isinstance(a,Foo)
print isinstance(a,Bar)
आउटपुट:
True
True
True
डिस्क्रिप्टर्स और डॉटेड लुकअप
डिस्क्रिप्टर्स वे ऑब्जेक्ट्स होते हैं जो (आमतौर पर) कक्षाओं के गुण होते हैं और जिनमें __get__
, __set__
, या __delete__
विशेष विधियां होती हैं।
डेटा डिस्क्रिप्टर्स में __set__
, या __delete__
कोई भी है
ये एक उदाहरण पर बिंदीदार लुक को नियंत्रित कर सकते हैं, और फ़ंक्शंस, staticmethod
, classmethod
और property
को लागू करने के लिए उपयोग किया जाता है। एक बिंदीदार देखने (जैसे उदाहरण foo
वर्ग के Foo
विशेषता को देख bar
- यानी foo.bar
) निम्नलिखित कलन विधि का उपयोग करता है:
bar
को कक्षा में देखा जाता है,Foo
। यदि यह वहाँ है और यह एक डेटा डिस्क्रिप्टर है , तो डेटा डिस्क्रिप्टर का उपयोग किया जाता है। इस तरहproperty
एक उदाहरण में डेटा तक पहुंच को नियंत्रित करने में सक्षम है, और उदाहरण इसे ओवरराइड नहीं कर सकते। यदि कोई डेटा डिस्क्रिप्टर नहीं है, तोbar
को उदाहरण में देखा जाता है__dict__
। यही कारण है कि हम एक उदाहरण से बिंदीदार लुकअप के साथ बुलाए गए तरीकों को ओवरराइड या ब्लॉक कर सकते हैं। यदिbar
उदाहरण में मौजूद है, तो इसका उपयोग किया जाता है। यदि नहीं, तो हमbar
लिए कक्षाFoo
। यदि यह एक डिस्क्रिप्टर है , तो डिस्क्रिप्टर प्रोटोकॉल का उपयोग किया जाता है। यह इस प्रकार है कि फ़ंक्शन (इस संदर्भ में, अनबाउंड तरीके),classmethod
, औरstaticmethod
को लागू किया जाता है। इसके बजाय यह केवल वस्तु को वहां लौटाता है, या एकAttributeError
क्लास के तरीके: अल्टरनेटिव इनिशियलाइज़र
कक्षा विधियाँ कक्षाओं के उदाहरण बनाने के लिए वैकल्पिक तरीके प्रस्तुत करती हैं। उदाहरण के लिए, आइए एक उदाहरण देखें।
मान लीजिए कि हमारे पास एक अपेक्षाकृत सरल Person
वर्ग है:
class Person(object):
def __init__(self, first_name, last_name, age):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.full_name = first_name + " " + last_name
def greet(self):
print("Hello, my name is " + self.full_name + ".")
इस वर्ग के उदाहरणों का निर्माण करने का तरीका आसान हो सकता है, पहले और अंतिम नाम के बजाय अलग नाम निर्दिष्ट करें। ऐसा करने का एक तरीका यह होगा कि last_name
एक वैकल्पिक पैरामीटर हो, और यह मानते हुए कि यदि यह नहीं दिया गया है, तो हमने पूरा नाम इसमें दिया:
class Person(object):
def __init__(self, first_name, age, last_name=None):
if last_name is None:
self.first_name, self.last_name = first_name.split(" ", 2)
else:
self.first_name = first_name
self.last_name = last_name
self.full_name = self.first_name + " " + self.last_name
self.age = age
def greet(self):
print("Hello, my name is " + self.full_name + ".")
हालांकि, इस बिट कोड के साथ दो मुख्य समस्याएं हैं:
पैरामीटर
first_name
औरlast_name
अब भ्रामक हैं, क्योंकि आपfirst_name
लिए पूरा नाम दर्ज कर सकते हैं। इसके अलावा, अगर इस तरह के लचीलेपन के अधिक मामले और / या अधिक पैरामीटर हैं, तो / elif / अन्यथा ब्रांचिंग कष्टप्रद तेजी ला सकती है।बहुत महत्वपूर्ण नहीं है, लेकिन फिर भी यह इंगित करने के लायक है: क्या होगा अगर
last_name
None
, लेकिनfirst_name
दो या दो से अधिक चीजों को अंतरिक्ष में विभाजित नहीं करता है? हमारे पास अभी तक इनपुट सत्यापन और / या अपवाद हैंडलिंग की एक और परत है ...
कक्षा के तरीके दर्ज करें। एकल from_full_name
होने के बजाय, हम एक अलग from_full_name
, जिसे from_full_name
कहा जाता है, और इसे (बिल्ट-इन) classmethod
डेकोरेटर से classmethod
।
class Person(object):
def __init__(self, first_name, last_name, age):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.full_name = first_name + " " + last_name
@classmethod
def from_full_name(cls, name, age):
if " " not in name:
raise ValueError
first_name, last_name = name.split(" ", 2)
return cls(first_name, last_name, age)
def greet(self):
print("Hello, my name is " + self.full_name + ".")
सूचना cls
के बजाय self
के लिए सबसे पहले तर्क के रूप में from_full_name
। कक्षा विधियां समग्र वर्ग पर लागू होती हैं, किसी दिए गए वर्ग का उदाहरण नहीं (जो कि आमतौर पर self
को दर्शाता है)। तो, अगर cls
हमारे है Person
वर्ग है, तो से दिए गए मान from_full_name
वर्ग विधि है Person(first_name, last_name, age)
है, जो का उपयोग करता है Person
की __init__
का एक उदाहरण बनाने के लिए Person
वर्ग। विशेष रूप से, यदि हमें एक Person
का उप- Employee
बनाना है, तो from_full_name
Employee
वर्ग में भी काम करेगा।
यह दिखाने के लिए कि यह उम्मीद के मुताबिक काम करता है, आइए __init__
में शाखा के बिना एक से अधिक तरीकों से Person
उदाहरण बनाएं:
In [2]: bob = Person("Bob", "Bobberson", 42)
In [3]: alice = Person.from_full_name("Alice Henderson", 31)
In [4]: bob.greet()
Hello, my name is Bob Bobberson.
In [5]: alice.greet()
Hello, my name is Alice Henderson.
अन्य संदर्भ:
https://docs.python.org/2/library/functions.html#classmethod
https://docs.python.org/3.5/library/functions.html#classmethod
वर्ग रचना
कक्षा रचना वस्तुओं के बीच स्पष्ट संबंधों की अनुमति देती है। इस उदाहरण में, लोग उन शहरों में रहते हैं जो देशों के हैं। रचना लोगों को उनके देश में रहने वाले सभी लोगों की संख्या तक पहुंचने की अनुमति देती है:
class Country(object):
def __init__(self):
self.cities=[]
def addCity(self,city):
self.cities.append(city)
class City(object):
def __init__(self, numPeople):
self.people = []
self.numPeople = numPeople
def addPerson(self, person):
self.people.append(person)
def join_country(self,country):
self.country = country
country.addCity(self)
for i in range(self.numPeople):
person(i).join_city(self)
class Person(object):
def __init__(self, ID):
self.ID=ID
def join_city(self, city):
self.city = city
city.addPerson(self)
def people_in_my_country(self):
x= sum([len(c.people) for c in self.city.country.cities])
return x
US=Country()
NYC=City(10).join_country(US)
SF=City(5).join_country(US)
print(US.cities[0].people[0].people_in_my_country())
# 15
बंदर पटकना
इस मामले में, "मंकी पैचिंग" का अर्थ है एक वर्ग के लिए एक नया चर या तरीका जोड़ना जो परिभाषित होने के बाद। उदाहरण के लिए, मान लें कि हमने क्लास A
को परिभाषित किया है
class A(object):
def __init__(self, num):
self.num = num
def __add__(self, other):
return A(self.num + other.num)
लेकिन अब हम बाद में कोड में एक और फ़ंक्शन जोड़ना चाहते हैं। मान लीजिए कि यह फ़ंक्शन निम्नानुसार है।
def get_num(self):
return self.num
लेकिन हम इसे A
में A
विधि के रूप में कैसे जोड़ते हैं? यह सरल है कि हम केवल उस कार्य को असाइनमेंट स्टेटमेंट के साथ A
में रखें।
A.get_num = get_num
यह काम क्यों करता है? क्योंकि फ़ंक्शंस किसी अन्य ऑब्जेक्ट की तरह ऑब्जेक्ट हैं, और विधियाँ फ़ंक्शंस हैं जो क्लास से संबंधित हैं।
फ़ंक्शन get_num
सभी मौजूदा (पहले से निर्मित) और साथ ही A
के नए उदाहरणों के लिए उपलब्ध होगा
ये परिवर्धन स्वचालित रूप से उस वर्ग (या उसके उपवर्ग) के सभी उदाहरणों पर उपलब्ध हैं। उदाहरण के लिए:
foo = A(42)
A.get_num = get_num
bar = A(6);
foo.get_num() # 42
bar.get_num() # 6
ध्यान दें, कुछ अन्य भाषाओं के विपरीत, यह तकनीक कुछ अंतर्निहित प्रकारों के लिए काम नहीं करती है, और इसे अच्छी शैली नहीं माना जाता है।
सभी कक्षा सदस्यों की सूची बनाना
dir()
फ़ंक्शन का उपयोग किसी वर्ग के सदस्यों की सूची प्राप्त करने के लिए किया जा सकता है:
dir(Class)
उदाहरण के लिए:
>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
केवल "गैर-जादू" सदस्यों के लिए देखना आम है। यह एक सरल समझ का उपयोग करके किया जा सकता है जो सदस्यों को __
शुरू न होने वाले नामों की सूची देता है:
>>> [m for m in dir(list) if not m.startswith('__')]
['append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
चेतावनियां:
कक्षाएं एक __dir__()
विधि को परिभाषित कर सकती हैं। यदि वह विधि dir()
कॉलिंग में मौजूद है तो __dir__()
कॉल करेगा, अन्यथा पायथन वर्ग के सदस्यों की सूची बनाने का प्रयास करेगा। इसका मतलब है कि dir फ़ंक्शन के अप्रत्याशित परिणाम हो सकते हैं। आधिकारिक अजगर प्रलेखन से महत्व के दो उद्धरण:
यदि ऑब्जेक्ट डीआईआर () प्रदान नहीं करता है, तो फ़ंक्शन ऑब्जेक्ट के तानाशाह विशेषता, यदि परिभाषित किया गया है, और इसके प्रकार ऑब्जेक्ट से जानकारी इकट्ठा करने की पूरी कोशिश करता है। परिणामी सूची आवश्यक रूप से पूरी नहीं होती है, और जब ऑब्जेक्ट कस्टम गेटटार () हो तो गलत हो सकता है।
नोट: क्योंकि dir () को मुख्य रूप से इंटरेक्टिव प्रॉम्प्ट पर उपयोग करने के लिए एक सुविधा के रूप में आपूर्ति की जाती है, यह नामों की एक दिलचस्प सेट की आपूर्ति करने की कोशिश करता है जितना कि यह एक कठोर या लगातार परिभाषित नामों की आपूर्ति करने की कोशिश करता है, और इसका विस्तृत व्यवहार बदल सकता है विज्ञप्ति। उदाहरण के लिए, मेटाक्लास विशेषताएँ परिणाम सूची में नहीं होती हैं जब तर्क एक वर्ग होता है।
कक्षाओं का परिचय
एक वर्ग, एक टेम्पलेट के रूप में कार्य करता है जो किसी विशेष वस्तु की बुनियादी विशेषताओं को परिभाषित करता है। यहाँ एक उदाहरण है:
class Person(object):
"""A simple class.""" # docstring
species = "Homo Sapiens" # class attribute
def __init__(self, name): # special method
"""This is the initializer. It's a special
method (see below).
"""
self.name = name # instance attribute
def __str__(self): # special method
"""This method is run when Python tries
to cast the object to a string. Return
this string when using print(), etc.
"""
return self.name
def rename(self, renamed): # regular method
"""Reassign and print the name attribute."""
self.name = renamed
print("Now my name is {}".format(self.name))
उपरोक्त उदाहरण को देखते समय कुछ बातें ध्यान देने योग्य हैं।
- वर्ग विशेषताओं (डेटा) और विधियों (कार्यों) से बना है।
- विशेषताएँ और विधियाँ बस सामान्य चर और कार्यों के रूप में परिभाषित की जाती हैं।
- जैसा कि संबंधित
__init__()
में उल्लेख किया गया है,__init__()
विधि को इनिशियलाइज़र कहा जाता है । यह अन्य ऑब्जेक्ट ओरिएंटेड भाषाओं में कंस्ट्रक्टर के बराबर है, और वह विधि है जो पहली बार तब चलती है जब आप एक नई ऑब्जेक्ट, या क्लास का नया उदाहरण बनाते हैं। - विशेषताएँ जो पूरी कक्षा पर लागू होती हैं, उन्हें पहले परिभाषित किया जाता है, और उन्हें कक्षा की विशेषताएँ कहा जाता है ।
- विशेषताएँ जो किसी वर्ग (वस्तु) के विशिष्ट उदाहरण पर लागू होती हैं, उदाहरण विशेषताएँ कहलाती हैं। वे आम तौर पर
__init__()
अंदर परिभाषित होते हैं; यह आवश्यक नहीं है, लेकिन यह अनुशंसित है (चूंकि__init__()
बाहर परिभाषित गुण__init__()
परिभाषित किए जाने से पहले एक्सेस किए जाने के जोखिम को चलाते हैं)। - कक्षा की परिभाषा में शामिल प्रत्येक विधि, अपने पहले पैरामीटर के रूप में प्रश्न में वस्तु को पारित करती है। इस पैरामीटर के लिए
self
शब्द का उपयोग किया जाता है (self
का उपयोग वास्तव में सम्मेलन द्वारा किया जाता है, क्योंकिself
शब्द का पायथन में कोई अंतर्निहित अर्थ नहीं है, लेकिन यह पायथन के सबसे सम्मानित सम्मेलनों में से एक है, और आपको हमेशा इसका पालन करना चाहिए)। - अन्य भाषाओं में ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग करने वाले लोग कुछ चीजों से आश्चर्यचकित हो सकते हैं। एक यह है कि पायथन में
private
तत्वों की कोई वास्तविक अवधारणा नहीं है, इसलिए सब कुछ, डिफ़ॉल्ट रूप से, C ++ / Javapublic
कीवर्ड के व्यवहार का अनुकरण करता है। अधिक जानकारी के लिए, इस पृष्ठ पर "निजी वर्ग के सदस्य" उदाहरण देखें। - कक्षा के कुछ तरीकों के निम्नलिखित रूप हैं:
__functionname__(self, other_stuff)
। ऐसे सभी तरीकों को "जादू के तरीके" कहा जाता है और पायथन में कक्षाओं का एक महत्वपूर्ण हिस्सा है। उदाहरण के लिए, पायथन में ऑपरेटर ओवरलोडिंग को जादुई तरीकों से लागू किया जाता है। अधिक जानकारी के लिए, संबंधित दस्तावेज़ देखें।
अब हम अपने Person
वर्ग के कुछ उदाहरण प्रस्तुत करते हैं!
>>> # Instances
>>> kelly = Person("Kelly")
>>> joseph = Person("Joseph")
>>> john_doe = Person("John Doe")
वर्तमान में हमारे पास तीन Person
वस्तुएं हैं, kelly
, joseph
, और john_doe
।
हम डॉट ऑपरेटर का उपयोग करके प्रत्येक उदाहरण से वर्ग की विशेषताओं तक पहुंच सकते हैं .
फिर से ध्यान दें कि वर्ग और उदाहरण की विशेषताओं के बीच का अंतर:
>>> # Attributes
>>> kelly.species
'Homo Sapiens'
>>> john_doe.species
'Homo Sapiens'
>>> joseph.species
'Homo Sapiens'
>>> kelly.name
'Kelly'
>>> joseph.name
'Joseph'
हम उसी डॉट ऑपरेटर का उपयोग करके कक्षा के तरीकों को निष्पादित कर सकते हैं .
:
>>> # Methods
>>> john_doe.__str__()
'John Doe'
>>> print(john_doe)
'John Doe'
>>> john_doe.rename("John")
'Now my name is John'
गुण
पायथन कक्षाएं गुणों का समर्थन करती हैं , जो नियमित ऑब्जेक्ट चर की तरह दिखती हैं, लेकिन कस्टम व्यवहार और प्रलेखन संलग्न करने की संभावना के साथ।
class MyClass(object):
def __init__(self):
self._my_string = ""
@property
def string(self):
"""A profoundly important string."""
return self._my_string
@string.setter
def string(self, new_value):
assert isinstance(new_value, str), \
"Give me a string, not a %r!" % type(new_value)
self._my_string = new_value
@string.deleter
def x(self):
self._my_string = None
वर्ग MyClass
की वस्तु के पास एक संपत्ति .string
दिखाई देगी । हालांकि, यह व्यवहार अब कसकर नियंत्रित है:
mc = MyClass()
mc.string = "String!"
print(mc.string)
del mc.string
उपरोक्त सिंटैक्स के साथ-साथ उपयोगी सिंटैक्स के रूप में, प्रॉपर्टी सिंटैक्स उन विशेषताओं को जोड़ने के लिए सत्यापन, या अन्य संवर्द्धन की अनुमति देता है। यह सार्वजनिक एपीआई के साथ विशेष रूप से उपयोगी हो सकता है - जहां उपयोगकर्ता को मदद का एक स्तर दिया जाना चाहिए।
गुणों का एक और सामान्य उपयोग वर्ग को 'आभासी विशेषताओं' को पेश करने में सक्षम करना है - विशेषताएँ जो वास्तव में संग्रहीत नहीं हैं लेकिन केवल अनुरोध किए जाने पर गणना की जाती हैं।
class Character(object):
def __init__(name, max_hp):
self._name = name
self._hp = max_hp
self._max_hp = max_hp
# Make hp read only by not providing a set method
@property
def hp(self):
return self._hp
# Make name read only by not providing a set method
@property
def name(self):
return self.name
def take_damage(self, damage):
self.hp -= damage
self.hp = 0 if self.hp <0 else self.hp
@property
def is_alive(self):
return self.hp != 0
@property
def is_wounded(self):
return self.hp < self.max_hp if self.hp > 0 else False
@property
def is_dead(self):
return not self.is_alive
bilbo = Character('Bilbo Baggins', 100)
bilbo.hp
# out : 100
bilbo.hp = 200
# out : AttributeError: can't set attribute
# hp attribute is read only.
bilbo.is_alive
# out : True
bilbo.is_wounded
# out : False
bilbo.is_dead
# out : False
bilbo.take_damage( 50 )
bilbo.hp
# out : 50
bilbo.is_alive
# out : True
bilbo.is_wounded
# out : True
bilbo.is_dead
# out : False
bilbo.take_damage( 50 )
bilbo.hp
# out : 0
bilbo.is_alive
# out : False
bilbo.is_wounded
# out : False
bilbo.is_dead
# out : True
एकल वर्ग
एक सिंगलटन एक ऐसा पैटर्न है जो एक वर्ग के तात्कालिकता को एक उदाहरण / वस्तु के लिए प्रतिबंधित करता है। अजगर सिंगलटन डिजाइन पैटर्न के बारे में अधिक जानकारी के लिए, यहां देखें।
class Singleton:
def __new__(cls):
try:
it = cls.__it__
except AttributeError:
it = cls.__it__ = object.__new__(cls)
return it
def __repr__(self):
return '<{}>'.format(self.__class__.__name__.upper())
def __eq__(self, other):
return other is self
एक और तरीका है अपनी कक्षा को सजाना। इस उत्तर से उदाहरण के बाद एक सिंगलटन वर्ग बनाएं:
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. 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.
Limitations: The decorated class cannot be inherited from.
"""
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)
उपयोग करने के लिए आप Instance
विधि का उपयोग कर सकते हैं
@Singleton
class Single:
def __init__(self):
self.name=None
self.val=0
def getName(self):
print(self.name)
x=Single.Instance()
y=Single.Instance()
x.name='I\'m single'
x.getName() # outputs I'm single
y.getName() # outputs I'm single