diff --git a/.gitignore b/.gitignore index 1992423..3f5acce 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ .vscode src/__pycache__/*.pyc src/pyBootCamp/__pycache__/*.cpython-310.pyc +src/pyBootCamp/__pycache__/*.pyc src/djangoProject/portfolio/env .pylintrc diff --git a/src/djangoProject/portfolio/requirements.txt b/src/djangoProject/portfolio/requirements.txt index a9d995c..5d7bb12 100644 --- a/src/djangoProject/portfolio/requirements.txt +++ b/src/djangoProject/portfolio/requirements.txt @@ -1,4 +1,154 @@ asgiref==3.5.2 +astroid==2.12.12 +click==8.1.3 +dill==0.3.6 Django==4.1.2 +Flask==2.2.2 +isort==5.10.1 +itsdangerous==2.1.2 +Jinja2==3.1.2 +lazy-object-proxy==1.8.0 +MarkupSafe==2.1.1 +mccabe==0.7.0 +platformdirs==2.5.4 +pycodestyle==2.9.1 +pydocstyle==6.1.1 +pylint==2.15.5 +pyobjc==8.5.1 +pyobjc-core==8.5.1 +pyobjc-framework-Accessibility==8.5.1 +pyobjc-framework-Accounts==8.5.1 +pyobjc-framework-AddressBook==8.5.1 +pyobjc-framework-AdServices==8.5.1 +pyobjc-framework-AdSupport==8.5.1 +pyobjc-framework-AppleScriptKit==8.5.1 +pyobjc-framework-AppleScriptObjC==8.5.1 +pyobjc-framework-ApplicationServices==8.5.1 +pyobjc-framework-AppTrackingTransparency==8.5.1 +pyobjc-framework-AudioVideoBridging==8.5.1 +pyobjc-framework-AuthenticationServices==8.5.1 +pyobjc-framework-AutomaticAssessmentConfiguration==8.5.1 +pyobjc-framework-Automator==8.5.1 +pyobjc-framework-AVFoundation==8.5.1 +pyobjc-framework-AVKit==8.5.1 +pyobjc-framework-BusinessChat==8.5.1 +pyobjc-framework-CalendarStore==8.5.1 +pyobjc-framework-CallKit==8.5.1 +pyobjc-framework-CFNetwork==8.5.1 +pyobjc-framework-ClassKit==8.5.1 +pyobjc-framework-CloudKit==8.5.1 +pyobjc-framework-Cocoa==8.5.1 +pyobjc-framework-Collaboration==8.5.1 +pyobjc-framework-ColorSync==8.5.1 +pyobjc-framework-Contacts==8.5.1 +pyobjc-framework-ContactsUI==8.5.1 +pyobjc-framework-CoreAudio==8.5.1 +pyobjc-framework-CoreAudioKit==8.5.1 +pyobjc-framework-CoreBluetooth==8.5.1 +pyobjc-framework-CoreData==8.5.1 +pyobjc-framework-CoreHaptics==8.5.1 +pyobjc-framework-CoreLocation==8.5.1 +pyobjc-framework-CoreMedia==8.5.1 +pyobjc-framework-CoreMediaIO==8.5.1 +pyobjc-framework-CoreMIDI==8.5.1 +pyobjc-framework-CoreML==8.5.1 +pyobjc-framework-CoreMotion==8.5.1 +pyobjc-framework-CoreServices==8.5.1 +pyobjc-framework-CoreSpotlight==8.5.1 +pyobjc-framework-CoreText==8.5.1 +pyobjc-framework-CoreWLAN==8.5.1 +pyobjc-framework-CryptoTokenKit==8.5.1 +pyobjc-framework-DeviceCheck==8.5.1 +pyobjc-framework-DictionaryServices==8.5.1 +pyobjc-framework-DiscRecording==8.5.1 +pyobjc-framework-DiscRecordingUI==8.5.1 +pyobjc-framework-DiskArbitration==8.5.1 +pyobjc-framework-DVDPlayback==8.5.1 +pyobjc-framework-EventKit==8.5.1 +pyobjc-framework-ExceptionHandling==8.5.1 +pyobjc-framework-ExecutionPolicy==8.5.1 +pyobjc-framework-ExternalAccessory==8.5.1 +pyobjc-framework-FileProvider==8.5.1 +pyobjc-framework-FileProviderUI==8.5.1 +pyobjc-framework-FinderSync==8.5.1 +pyobjc-framework-FSEvents==8.5.1 +pyobjc-framework-GameCenter==8.5.1 +pyobjc-framework-GameController==8.5.1 +pyobjc-framework-GameKit==8.5.1 +pyobjc-framework-GameplayKit==8.5.1 +pyobjc-framework-ImageCaptureCore==8.5.1 +pyobjc-framework-IMServicePlugIn==8.5.1 +pyobjc-framework-InputMethodKit==8.5.1 +pyobjc-framework-InstallerPlugins==8.5.1 +pyobjc-framework-InstantMessage==8.5.1 +pyobjc-framework-Intents==8.5.1 +pyobjc-framework-IOSurface==8.5.1 +pyobjc-framework-iTunesLibrary==8.5.1 +pyobjc-framework-KernelManagement==8.5.1 +pyobjc-framework-LatentSemanticMapping==8.5.1 +pyobjc-framework-LaunchServices==8.5.1 +pyobjc-framework-libdispatch==8.5.1 +pyobjc-framework-LinkPresentation==8.5.1 +pyobjc-framework-LocalAuthentication==8.5.1 +pyobjc-framework-MapKit==8.5.1 +pyobjc-framework-MediaAccessibility==8.5.1 +pyobjc-framework-MediaLibrary==8.5.1 +pyobjc-framework-MediaPlayer==8.5.1 +pyobjc-framework-MediaToolbox==8.5.1 +pyobjc-framework-Metal==8.5.1 +pyobjc-framework-MetalKit==8.5.1 +pyobjc-framework-MetalPerformanceShaders==8.5.1 +pyobjc-framework-MetalPerformanceShadersGraph==8.5.1 +pyobjc-framework-MLCompute==8.5.1 +pyobjc-framework-ModelIO==8.5.1 +pyobjc-framework-MultipeerConnectivity==8.5.1 +pyobjc-framework-NaturalLanguage==8.5.1 +pyobjc-framework-NetFS==8.5.1 +pyobjc-framework-Network==8.5.1 +pyobjc-framework-NetworkExtension==8.5.1 +pyobjc-framework-NotificationCenter==8.5.1 +pyobjc-framework-OpenDirectory==8.5.1 +pyobjc-framework-OSAKit==8.5.1 +pyobjc-framework-OSLog==8.5.1 +pyobjc-framework-PassKit==8.5.1 +pyobjc-framework-PencilKit==8.5.1 +pyobjc-framework-Photos==8.5.1 +pyobjc-framework-PhotosUI==8.5.1 +pyobjc-framework-PreferencePanes==8.5.1 +pyobjc-framework-PushKit==8.5.1 +pyobjc-framework-Quartz==8.5.1 +pyobjc-framework-QuickLookThumbnailing==8.5.1 +pyobjc-framework-ReplayKit==8.5.1 +pyobjc-framework-SafariServices==8.5.1 +pyobjc-framework-SceneKit==8.5.1 +pyobjc-framework-ScreenSaver==8.5.1 +pyobjc-framework-ScreenTime==8.5.1 +pyobjc-framework-ScriptingBridge==8.5.1 +pyobjc-framework-SearchKit==8.5.1 +pyobjc-framework-Security==8.5.1 +pyobjc-framework-SecurityFoundation==8.5.1 +pyobjc-framework-SecurityInterface==8.5.1 +pyobjc-framework-ServiceManagement==8.5.1 +pyobjc-framework-Social==8.5.1 +pyobjc-framework-SoundAnalysis==8.5.1 +pyobjc-framework-Speech==8.5.1 +pyobjc-framework-SpriteKit==8.5.1 +pyobjc-framework-StoreKit==8.5.1 +pyobjc-framework-SyncServices==8.5.1 +pyobjc-framework-SystemConfiguration==8.5.1 +pyobjc-framework-SystemExtensions==8.5.1 +pyobjc-framework-UniformTypeIdentifiers==8.5.1 +pyobjc-framework-UserNotifications==8.5.1 +pyobjc-framework-UserNotificationsUI==8.5.1 +pyobjc-framework-VideoSubscriberAccount==8.5.1 +pyobjc-framework-VideoToolbox==8.5.1 +pyobjc-framework-Virtualization==8.5.1 +pyobjc-framework-Vision==8.5.1 +pyobjc-framework-WebKit==8.5.1 +pyttsx3==2.90 +snowballstemmer==2.2.0 sqlparse==0.4.3 -pip>=22.3 +tomli==2.0.1 +tomlkit==0.11.6 +Werkzeug==2.2.2 +wrapt==1.14.1 diff --git a/src/pyBootCamp/11_practice07.py b/src/pyBootCamp/11_practice07.py new file mode 100644 index 0000000..38b4442 --- /dev/null +++ b/src/pyBootCamp/11_practice07.py @@ -0,0 +1,192 @@ +# module to explore super object. + + +class A: + """Class used as base class. + + + Attributes: + ---------- + val (int): Integer class based attribute. + + Methods: + -------- + __str__() : Instance overriding string method returning the name of the class. + """ + # class attribute + val = 10 + + def __str__(self) -> str: + """Returns the name of the class. + + + Returns: + ------- + qualified name of the class as string. + """ + return self.__class__.__qualname__ + + +class B(A): + """Class deriving from A. + + + Attributes: + ----------- + val (int): Integer class based attribute. + + Methods: + -------- + __str__() : Instance overriding string method returning the name of the class. + """ + val = 2 + + def __str__(self) -> str: + """Returns the name of the class. + + + Returns: + -------- + The qualified name of the class as a string. + """ + return self.__class__.__qualname__ + + +class C(A): + """Class deriving from A. + + + Attributes: + ----------- + val (int): Integer class based attribute. + + Methods: + -------- + __str__() : Instance overriding string method returning the name of the class. + """ + val = 1 + + def __str__(self) -> str: + """Returns the name of the class. + + + Returns: + -------- + The qualified name of the class as a string. + """ + return self.__class__.__qualname__ + + +class X(A): + """Class deriving from A. + + + Attributes: + ----------- + val (int): Integer class based attribute. + + Methods: + -------- + __str__() : Instance overriding string method returning the name of the class. + """ + val = 1 + + def __str__(self) -> str: + """Returns the name of the class. + + + Returns: + -------- + The qualified name of the class as a string. + """ + return self.__class__.__qualname__ + + +class Y(X): + """Class deriving from X. + + + Attributes: + ----------- + val (int): Integer class based attribute. + + Methods: + -------- + __str__() : Instance overriding string method returning the name of the class. + """ + val = 3 + + def __str__(self) -> str: + """Returns the name of the class. + + + Returns: + -------- + The qualified name of the class as a string. + """ + return self.__class__.__qualname__ + + +class Z(Y, X): + """Class deriving from Y and X. + + + Attributes: + ----------- + val (int): Integer class based attribute. + + Methods: + -------- + __str__() : Instance overriding string method returning the name of the class. + """ + val = 5 + + def __str__(self) -> str: + """Returns the name of the class. + + + Returns: + -------- + The qualified name of the class as a string. + """ + return self.__class__.__qualname__ + + +class D(C, Z, B): + """Class deriving from B and C. + + + Attributes: + ----------- + val (int): Integer class based attribute. + """ + val = 5 + + + +if __name__=="__main__": + a = A() + b = B() + c = C() + d = D() + print("Class:",d) + print(f"Method resolution order: {D.__mro__}") + print(f"Is object of {d} an instance of {a}: {isinstance(b, A)}") + print(f"Is object of {d} a subtype of itself: {issubclass(type(d), D)}") + + _super = super(C, d) + print(f"Type of _super is {_super}, method resolution order: {type(_super).__mro__}") + print(f"The val attribute: {_super.val}") + + _super = super(D, d) + print(f"Type of _super is {_super}, method resolution order: {type(_super).__mro__}") + print(f"The val attribute: {_super.val}") + + _super = super(B, d) + print(f"The type of _super is {_super.__thisclass__}, the object or type of super's second argument is {_super.__self__} and {_super.__self_class__}") + + _super = super(D) + print(f"The type of _super is {_super.__thisclass__}, the object or type of super's second argument is {_super.__self__} and {_super.__self_class__}") + + D.parent = _super + print(f"The type of _super is {d.parent.__thisclass__}, the object or type of super's second argument is {d.parent.__self__} and {d.parent.__self_class__}") \ No newline at end of file diff --git a/src/pyBootCamp/11_practice08.py b/src/pyBootCamp/11_practice08.py new file mode 100644 index 0000000..3f7ac07 --- /dev/null +++ b/src/pyBootCamp/11_practice08.py @@ -0,0 +1,87 @@ +# extending built-in types using super object. +from typing import Any +from collections import OrderedDict +import logging + + +class LoggingDict(dict): + """Class extending python dict. + + + Methods: + ------- + __setitem__(key, value): Logs the key and value then adds the key-value pair in dictionary. + __getitem__(__key): Fetches and returns the value for given key in dictionary. + """ + def __init__(self): + self.logger = logging.getLogger(name=__file__) + logging.basicConfig(level=logging.INFO) + + def __setitem__(self, key, value) -> None: + """Setting the dictionary with key, value pair. + + Attr: + ----- + key: Key of dictionary. + value: Value for key in dictionary. + """ + self.logger.info("Setting to %s, %s, in %s" % (key, value, super().__thisclass__)) + super().__setitem__(key, value) + + def __getitem__(self, __key: Any) -> Any: + """Fetches the value of given key from dictionary. + + + Attr: + ----- + __key: The key for lookup in the dictionary. + + Returns: + -------- + Value associated with given key in dictionary. + """ + self.logger.info("Fetching value in %s for key: %s" % (super().__thisclass__, __key)) + return super().__getitem__(__key) + + +class LoggingOD(LoggingDict, OrderedDict): + """Logging ordered dictionary. + + + Methods: + -------- + __setitem__(key, value): Adds the key-value pair in ordered dictionary and logs its content. + """ + def __init__(self) -> None: + """Initialize the LoggingOD class with ordered dict.""" + super().__init__() + self.logger.info(msg=f"Logged ordered dict in {super().__thisclass__}: {self}") + + def __setitem__(self, key, value) -> None: + """Setting the ordered dictionary with key, value pair. + + + Attr: + ----- + key: Key of ordered dictionary. + value: Value for key in ordered dictionary. + """ + super().__setitem__(key=key, value=value) + self.logger.info(msg=f"Logged ordered dict in {super().__thisclass__}: {self}") + + +if __name__=="__main__": + # logging dict key/value pairs. + logging_dict = LoggingDict() + logging_dict["apple"] = 2 + logging_dict["orange"] = 4 + print("No. of apples:", logging_dict["apple"]) + print("No. of oranges:", logging_dict["orange"]) + + # logging ordered dict key/value pairs. + logging_od = LoggingOD() + logging_od["banana"] = 12 + print("No. of bananas:", logging_od["banana"]) + + # updating dictionary in ordered manner. + logging_od.update(logging_dict) \ No newline at end of file diff --git a/src/pyBootCamp/11_practice09.py b/src/pyBootCamp/11_practice09.py new file mode 100644 index 0000000..abf32a0 --- /dev/null +++ b/src/pyBootCamp/11_practice09.py @@ -0,0 +1,74 @@ +# module to implement cooperative multiple inheritance. +# passing all required arguments along with keyword arguments and a keyword arguments dictionary. +# dispatching method calls from caller to callee ensuring argument patterns are matched. +# In the object class while dispatching the call using super the method is not found. +# Badly designed classes for cooperatively dispatching method calls along mutiple inheritance chain. + + +class Shape(): + """Class depicting a shape with a name. + + + Attributes: + ----------- + shapename (str): Name of the shape instance. + + Methods: + ------- + draw(): Draws a shape by printing its name and dispatches the call to its parent in inheritance chain. + """ + def __init__(self, _name, **kwargs) -> None: + """Initialize the shape instance. + + + Args: + ----- + _name (str): Name of the shape. + **kwargs (dict): Dictionary of keyword arguments. + Each keyword argument in **kwargs required by the caller gets stripped-off. + The method is dispatched to the callee in method resolution order with remaining arguments in **kwargs. + """ + self.shapename = _name + super().__init__(**kwargs) + + def draw(self) -> None: + """Drawing by printing the shape name.""" + print('Drawing. Setting shape to:', self.shapename) + return super().draw() + + +class ColoredShape(Shape): + """Class depicting a shape with color and a name. + + + Attributes: + ---------- + color (str): Color of the shape instance. + + Methods: + -------- + draw(): Draws the shape by printing its color and and dispatches the call to its parent in inheritance chain to print its name. + """ + def __init__(self, _color, **kwargs) -> None: + """Initialize the shape instance color. + + + Args: + ----- + _color: Color of the shape. + **kwargs (dict): Dictionary of keyword arguments. + Each keyword argument in **kwargs required by the caller gets stripped-off. + The method is dispatched to the callee in method resolution order with remaining arguments in **kwargs. + """ + self.color = _color + super().__init__(**kwargs) + + def draw(self) -> None: + """Drawing by printing the shape color.""" + print('Drawing. Setting color to:', self.color) + return super().draw() + + +if __name__=="__main__": + shape = ColoredShape(_color="Red", _name="Circle") + shape.draw() diff --git a/src/pyBootCamp/11_practice10.py b/src/pyBootCamp/11_practice10.py new file mode 100644 index 0000000..d8d7b51 --- /dev/null +++ b/src/pyBootCamp/11_practice10.py @@ -0,0 +1,152 @@ +# Cooperative multiple inheritance with method arguments pattern ensured. +# Class designed with method of interest always defined in caller. +# Root class to handle method call to callee by caller. +# Root class checks if the method exists in callee before dispatching method call to callee. +# Good design for cooperative multiple inheritance with classes in dynamic execution environment. +# Adapter class to integrate with third-party Movable class that doesn't conform to cooperative multiple inheritance rules. +from movables import Movable + + +class Root: + """Parent class. + This class eats away any method dispatched by callers down the inheritance chain + without dispatching it to the base object class at top of method resolution order. + + Prevents AttributeErrorException from being raised by callers dispatching method to callee with no such method defined. + + + Methods: + -------- + draw(): Draws a shape without dispatching the call any further up the inheritance chain using super. + """ + def draw(self): + """Eats up the draw method dispatched by caller subtype in inheritance chain.""" + # the delegation chain stops here + assert not hasattr(super(), 'draw') + + +class Shape(Root): + """Shape with a name. + + + Attributes: + ----------- + shapename (str): Name of the shape instance. + + Methods: + -------- + draw(): Draws a shape by printing name of the shape instance. + """ + def __init__(self, shapename, **kwds): + """Initializes a shape instance with a name. + + + Args: + ----- + shapename (str): Name of the shape. + **kwargs (dict): Dictionary of keyword arguments. + Each keyword argument in **kwargs required by the caller gets stripped-off. + The method is dispatched to the callee in method resolution order with remaining arguments in **kwargs. + """ + self.shapename = shapename + super().__init__(**kwds) + + def draw(self): + """Drawing by printing the shape name.""" + print('Drawing. Setting shape to:', self.shapename) + super().draw() + + +class MovableAdapter(Root): + """Adapter class. + This class integrates with Movable class by composition. + Follows the rules of cooperative multiple inheritance. + + + Attributes: + ----------- + movable (Movable): Movable class instance composed in adapter. + + Methods: + -------- + draw(): Draws the shape by specifying the co-ordinates to start drawing + and dispatches the call to its parent in inheritance chain. + """ + def __init__(self, x, y, **kwargs) -> None: + """Initializing MovableAdapter instance. + The adapter composes incompatible Movable class. + Integrates with rules of cooperative multiple inheritance. + + + Args: + ----- + x (int): Position depicting x co-ordinate. + y (int): Position depicting x co-ordinate. + **kwargs (dict): Dictionary of keyword arguments. + Each keyword argument in **kwargs required by the caller gets stripped-off. + The method is dispatched to the callee in method resolution order with remaining arguments in **kwargs. + """ + self.movable = Movable(x, y) + return super().__init__(**kwargs) + + def draw(self): + """Draws the shape specifying the position.""" + self.movable.draw() + return super().draw() + + +class ColoredShape(Shape): + """Shape with color and a name. + + + Attributes: + ----------- + color (str): Color of shape instance. + + Methods: + -------- + draw(): Draws the shape by printing its color and dispatches the call to its parent in inheritance chain to print its name. + """ + def __init__(self, color, **kwds): + """Initializes the color with a name of shape instance. + + + Attributes: + ----------- + color (str): Color of the shape. + **kwargs (dict): Dictionary of keyword arguments. + Each keyword argument in **kwargs required by the caller gets stripped-off. + The method is dispatched to the callee in method resolution order with remaining arguments in **kwargs. + """ + self.color = color + super().__init__(**kwds) + + def draw(self): + """Drawing by printing the shape color.""" + print('Drawing. Setting color to:', self.color) + super().draw() + + +class MovableColoredShape(ColoredShape, MovableAdapter): + """Extends the ColoredShape instance by composing MovableAdapter. + The draw method extends the color and shape by printing the + position of the co-ordinates for drawing the given shape. + """ + def __init__(self, **kwargs) -> None: + """Initializes MovableColoredShape instance and its parent classes up the method resolution order. + + + Attributes: + ----------- + **kwargs (dict): Dictionary of keyword arguments. Each keyword argument in **kwargs required by the caller gets stripped-off. The method gets dispatched to the callee in method resolution order with remaining arguments in **kwargs. + """ + print("Method resolution order of", super().__thisclass__, "is", super().__self_class__.__mro__) + return super().__init__(**kwargs) + + +if __name__=="__main__": + shape = ColoredShape(color="Blue", shapename="Square") + shape.draw() + + movable_shape = MovableColoredShape(color="Red", shapename="Triangle", x=10, y=20) + movable_shape.draw() \ No newline at end of file diff --git a/src/pyBootCamp/descriptors.py b/src/pyBootCamp/descriptors.py new file mode 100644 index 0000000..45195d0 --- /dev/null +++ b/src/pyBootCamp/descriptors.py @@ -0,0 +1,39 @@ +# read-only data descriptor providing a constant integer value. + + +class Verbose_attribute(): + """A class representing read-only data descriptor. + + + Returns: + -------- + A constant integer value 43. + """ + def __get__(self, instance, type=type(int)) -> int: + """Fetches the value of descriptor. + + + Args: + ---- + instance (object): Descriptor instance. + type (type): Type of object fetched by descriptor. + + Returns: + -------- + A constant integer value 43. + """ + print("accessing the attribute to get the value") + return 43 + + def __set__(self, instance, value: int) -> None: + """Set the value for descriptor. + + + Args: + ----- + instance (object): Descriptor instance. + value (int): Integer value to set the descriptor. + """ + print("accessing the attribute to set the value") + raise AttributeError("Cannot change the value") + \ No newline at end of file diff --git a/src/pyBootCamp/foo.py b/src/pyBootCamp/foo.py new file mode 100644 index 0000000..62aa4e5 --- /dev/null +++ b/src/pyBootCamp/foo.py @@ -0,0 +1,33 @@ +# module showcasing usage of descriptor attribute. +from descriptors import Verbose_attribute + + +class Foo(): + """Class containing a descriptor attribute. + + + Attributes: + ---------- + desc: Read-Only data descriptor as a class attribute. + """ + desc = Verbose_attribute() + + +if __name__=="__main__": + # instantiating foo class. + foo = Foo() + + # accessing descriptor attribute. + x = foo.desc + print(x) + + # foo class dictionary. + class_dict = Foo.__dict__ + print(f"{foo.__class__.__qualname__} dictionary lookup:",class_dict) + + # attempting to set descriptor. + try: + foo.desc = 0 + except AttributeError as attex: + print(attex) + diff --git a/src/pyBootCamp/movables.py b/src/pyBootCamp/movables.py new file mode 100644 index 0000000..0ebdfba --- /dev/null +++ b/src/pyBootCamp/movables.py @@ -0,0 +1,31 @@ +# Implements Movable class that doesn't follow cooperative multiple inheritance techniques. + + +class Movable(): + """Movable class with co-ordinates to draw. + + + Attributes: + ---------- + x (int): Position depicting x co-ordinate. + y (int): Position depicting y co-ordinate. + + Methods: + -------- + draw(): Specifies x and y co-ordinates respectively for drawing. + """ + def __init__(self, x, y) -> None: + """Initializes the position for drawing a Movable instance. + + + Args: + ----- + x (int): Position depicting x co-ordinate. + y (int): Position depicting y co-ordinate. + """ + self.x = x + self.y = y + + def draw(self) -> None: + """Specifies the co-ordinates to draw a movable instance.""" + print('Drawing at position:', self.x, self.y) \ No newline at end of file diff --git a/src/pyBootCamp/orderedcounter.py b/src/pyBootCamp/orderedcounter.py new file mode 100644 index 0000000..484e19f --- /dev/null +++ b/src/pyBootCamp/orderedcounter.py @@ -0,0 +1,24 @@ +# Composing Counter class and Ordered dict class from collections module. +# Extends both the classs to provide the functionality of an OrderedCounter class. +from collections import Counter, OrderedDict + + +class OrderedCounter(Counter,OrderedDict): + """Class composing Counter and OrderedDict. + OrderedCounter is a counter that remembers the order in which elements are inserted into dictionary. + """ + def __repr__(self) -> str: + """Represents OrderedCounter instance with class name and ordered dictionary of its instances.""" + return '%s(%r)' % (self.__class__.__name__, + OrderedDict(self)) + + def __reduce__(self): + return self.__class__, (OrderedDict(self),) + + +if __name__=="__main__": + oc = OrderedCounter("abracadabra") + print(oc) + # adds to the counter value for given key instad of replacing it. + oc.update(r=2) + print(oc)