From 530ab64b56e4d6600a88edae4c48d9ab519fdb07 Mon Sep 17 00:00:00 2001 From: avimehenwal Date: Tue, 21 Jul 2020 22:26:39 +0200 Subject: [PATCH] feat(website): :tada: Add homepage update css styles variables 255 Files | 461M | develop | 6 files changed, 425 insertions(+), 300 deletions(-) --- docs/.vuepress/config.js | 4 +- docs/.vuepress/styles/index.styl | 30 ++- docs/.vuepress/styles/palette.styl | 11 +- docs/Projects/test.md | 52 ++++- docs/README.md | 310 ++++------------------------ docs/Tutorials/00_material.md | 318 +++++++++++++++++++++++++++-- 6 files changed, 425 insertions(+), 300 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 91e5792..aecac19 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -91,8 +91,8 @@ module.exports = { { type: 'quote', defaultTitle: 'Anonymous', - before: info => `

${info}

`, - after: info => `${info}
`, + before: info => `
`, + after: info => `

${info}

`, }, ] ], diff --git a/docs/.vuepress/styles/index.styl b/docs/.vuepress/styles/index.styl index 1c5bcc8..780d2d9 100644 --- a/docs/.vuepress/styles/index.styl +++ b/docs/.vuepress/styles/index.styl @@ -12,8 +12,8 @@ dt // clear: left; // width: 100px; // text-align: right; - font-weight: bold; - color: #4B8BBE; + font-weight: bold + color: $blueL // text-decoration: underline; dt::after @@ -26,19 +26,13 @@ dd .social-share-icon-svg color: $badgeErrorColor -mark - padding-left: 5px - padding-right: 5px - border-radius: 5px - padding-top: 2px - padding-bottom: 2px - // container styles .theorem margin 1rem 0 padding .1rem 1.5rem border-radius $BorderRadius background-color #f0f4f8 + text-align center .title font-weight bold @@ -64,3 +58,21 @@ mark font-size: 1.2rem font-style: italic text-align center + +// Latex Styles +mjx-container.MathJax + font-weight: bold + padding: $Padding + border-radius: $BorderRadius + background: $containerbg + color: $githubRed + +mark + border-radius: $BorderRadius + padding: $Padding + background: $yellowL + color: $greyL + // padding-left: 5px + // padding-right: 5px + // padding-top: 2px + // padding-bottom: 2px diff --git a/docs/.vuepress/styles/palette.styl b/docs/.vuepress/styles/palette.styl index 99d79d4..3505ba0 100644 --- a/docs/.vuepress/styles/palette.styl +++ b/docs/.vuepress/styles/palette.styl @@ -21,5 +21,14 @@ $MQMobile = 719px $MQMobileNarrow = 419px // custome configs +$BorderRadius = 0.4rem +$Padding = 0.3rem // all sides -$BorderRadius = 0.4rem \ No newline at end of file +// Python color pallet L-lighter shade D - Darker varient +$blueL = #4B8BBE +$blueD = #306998 +$yellowL = #FFE873 +$yellowD = #FFD43B +$greyL = #646464 +$containerbg = #f0f4f8 +$githubRed = #d73a49 diff --git a/docs/Projects/test.md b/docs/Projects/test.md index f69cdb3..f690594 100644 --- a/docs/Projects/test.md +++ b/docs/Projects/test.md @@ -4,6 +4,7 @@ + ## 1.1. markdown-it-ins ++inserted++ @@ -64,9 +65,48 @@ is maintained by the W3C. <<< @/../src/hidden_features.py#snippet{5} -## 1.9. Mermaid +## 1.9. Custom Containers + +::: quote alexander +Some quote please +::: + +::: quote +Some quote without header +::: + + +::: theorem Newton's First Law +In an inertial frame of reference, an object either remains at rest or continues to move at a constant velocity, unless acted upon by a force. + + ::: right + From [Wikipedia](https://en.wikipedia.org/wiki/Newton%27s_laws_of_motion) + ::: +::: + +::: tip +Tip container of `@vuepress/theme-default` +::: + +::: right +From [Wikipedia](https://en.wikipedia.org/wiki/Newton%27s_laws_of_motion) +::: + +## 1.10. Badges + +sadnfoidsnofsd klsndfi nsidfon siodnf dsf + +isdbfios nfosdnf osdn fosnf osndfion siodnfosdn + +sndofkn odsnfios ndfioksnd iofnsiodfnios nfio + +sndofkn odsnfios ndfioksnd iofnsiodfnios nfio + +dsifnioa fnioasnf ionadsio fniodfn oidn f + +## 1.11. Mermaid -### 1.9.1. Sequence Diagram +### 1.11.1. Sequence Diagram ``` mermaid sequenceDiagram @@ -76,7 +116,7 @@ loop every minute end ``` -### 1.9.2. Pie Chart +### 1.11.2. Pie Chart ```mermaid pie title Pets adopted by volunteers @@ -85,7 +125,7 @@ pie title Pets adopted by volunteers "Rats" : 15 ``` -### 1.9.3. Git graph +### 1.11.3. Git graph ```mermaid gitGraph: @@ -106,7 +146,7 @@ commit merge newbranch ``` -### 1.9.4. Gantt Chart +### 1.11.4. Gantt Chart [Basics of Gantt Chart](https://avimehenwal.in/blog/gantt-chart/) @@ -142,7 +182,7 @@ Add another diagram to demo page :48h ``` -### 1.9.5. Add all markdown packages +### 1.11.5. Add all markdown packages ``` yarn add -D markdown-it-container markdown-it-footnote markdown-it-deflist markdown-it-emoji markdown-it-mark markdown-it-abbr markdown-it-sub markdown-it-sup markdown-it-ins diff --git a/docs/README.md b/docs/README.md index b3d7e4c..7918284 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,302 +1,82 @@ -# 1. Python docs +--- +home: true +heroImage: /logo.svg +heroText: Programming Language +tagline: blog by avi πŸ˜ƒ mehenwal +actionText: πŸ‘ Get Started ⛳️ +actionLink: /tutorials/ +features: +- title: πŸ‘¨β€πŸ‘©β€πŸ‘§ General purpose programming + details: Write short automation scritps to complicated CLI tools or web-apps. Use any programming paradigm you are familiar with. Everything is possible +- title: πŸ›  Both compiled and interpreted + details: Depends on implementation. CPython implementation is first compiled to bytecode by PVM and then sent for execution by CPU. REPL uses interpretor to execute python +- title: πŸ–₯ Cross - Platform + details: Write once and use everywhere. Great cross platform portability, run same softwares on your machines and then deploy them cloud servers +footer: MIT Licensed | Avi Mehenwal πŸ…°οΈ +--- -![Python programming logo](/logo.svg) +::: theorem -::: tip Science and Engineering +### :woman_scientist: Principle of Science and Engineering :man_scientist: -> Try to do good science rather than popular science. +***"Try to do ==good science== rather than :money_mouth_face: popular science"*** -Liberral Education -: Learn something about everything and everything about something. -::: - -## 1.1. Pythonic - -- All generators are iterators BUT not all iterators are generators -- Generators are usually attached to functions have `next()` method and `yield` -- Iterator creates a list generator generates ONE item at a time for computation - * Iterator *advantages* Creates item for computation one at a time and does not consumes more memory. **Lazy Loading** -- Python supports MULTIPLE INHERITANCE - -```python -class Base1: - pass - -class Base2: - pass +#### Liberal Education -class MultiDerived(Base1, Base2): - pass +***"Learn something about everything and everything about something"*** -class Base: - pass +### :innocent: Zen of Python :innocent: -class Derived1(Base): - pass +Beautiful is better than ugly. -class Derived2(Derived1): - pass -``` +Explicit is better than implicit. -## 1.2. GIL - Global Interpreted Lock +Simple is better than complex. -Python's GIL is intended to serialize access to interpreter internals from different threads. On multi-core systems, it means that multiple threads can't effectively make use of multiple cores. (If the GIL didn't lead to this problem, most people wouldn't care about the GIL - it's only being raised as an issue because of the increasing prevalence of multi-core systems.) -Note that Python's GIL is only really an issue for CPython, the reference implementation. Jython and IronPython don't have a GIL. As a Python developer, you don't generally come across the GIL unless you're writing a C extension. C extension writers need to release the GIL when their extensions do blocking I/O, so that other threads in the Python process get a chance to run. +Complex is better than complicated. -## 1.3. OOP - Object Oriented Programming +Flat is better than nested. -### 1.3.1. Python Operator Overloading +Sparse is better than dense. -Python operators work for built-in classes. But same operator behaves differently with different types. +Readability counts. -**For example,** the `+` operator will, perform arithmetic addition on two numbers, merge two lists and concatenate two strings. This feature in Python, that allows same operator to have different meaning according to the context is called operator overloading. +Special cases aren't special enough to break the rules. -### 1.3.2. Polymorphism +Although practicality beats purity. -A common real example in Python is **file-like objects**. Besides actual files, several other types, including `StringIO` and `BytesIO`, are file-like. A method that acts as files can also act on them because they support the required methods (e.g. read, write). +Errors should never pass silently. -### 1.3.3. Encapsulation (Accessability) +Unless explicitly silenced. -private attributes are defined by special syntax `self.__a` same with methods. -`def __methodName(self):` +In the face of ambiguity, refuse the temptation to guess. -Major Difference between Python 2 and Python 3: +There should be one-- and preferably only one --obvious way to do it. -1. print is now a function instead of keyword -2. xrange (iterable) is now replaced with range() -3. python 3 supports Unicode -4. raw_input() is replaced by input() method +Although that way may not be obvious at first unless you're Dutch. -### 1.3.4. Python Classes and Functions +Now is better than never. -- New Classes and old classes. Diffreence ? -- Though classmethod and staticmethod are quite similar, there's a slight difference in usage for both entities: classmethod must have a reference to a class object as the first parameter, whereas staticmethod can have no parameters at all. -- Classmethods leads to Factory Design pattern in python +Although never is often better than *right* now. -### 1.3.5. Python @staticmethod +If the implementation is hard to explain, it's a bad idea. -Static methods are a special case of methods. Sometimes, you'll write code that belongs to a class, but that doesn't use the object itself at all. For example: +If the implementation is easy to explain, it may be a good idea. -```python -class Pizza(object): - @staticmethod - def mix_ingredients(x, y): - return x + y +Namespaces are one honking great idea -- let's do more of those! - def cook(self): - return self.mix_ingredients(self.cheese, self.vegetables) -``` - -In such a case, writing mix_ingredients as a non-static method would work too, but it would provide it a self argument that would not be used. Here, the decorator @staticmethod buys us several things: - -::: tip @staticmethod -Python doesn't have to instantiate a bound-method for each Pizza object we instiantiate. -Bound methods are objects too, and creating them has a cost. Having a static method avoids that: +::: right +[Tim Peters](https://en.wikipedia.org/wiki/Tim_Peters_(software_engineer)) ::: -```python ->>> Pizza().cook is Pizza().cook -False ->>> Pizza().mix_ingredients is Pizza.mix_ingredients -True ->>> Pizza().mix_ingredients is Pizza().mix_ingredients -True -``` - -It eases the readability of the code: seeing @staticmethod, we know that the method does not depend on the state of object itself; -It allows us to override the mix_ingredients method in a subclass. If we used a function mix_ingredients defined at the top-level of our module, a class inheriting from Pizza wouldn't be able to change the way we mix ingredients for our pizza without overriding cook itself. - -### 1.3.6. Python @classmethods - -Having said that, what are class methods? Class methods are methods that are not bound to an object, but to… a class! - -```python ->>> class Pizza(object): -... radius = 42 -... @classmethod -... def get_radius(cls): -... return cls.radius -... ->>> ->>> Pizza.get_radius -> ->>> Pizza().get_radius -> ->>> Pizza.get_radius is Pizza().get_radius -True ->>> Pizza.get_radius() -42 -``` - -Whatever the way you use to access this method, it will be always bound to the class it is attached too, and its first argument will be the class itself (remember that classes are objects too). -When to use this kind of methods? Well class methods are mostly useful for two types of methods: -Factory methods, that are used to create an instance for a class using for example some sort of pre-processing. If we use a @staticmethod instead, we would have to hardcode the Pizza class name in our function, making any class inheriting from Pizza unable to use our factory for its own use. - -```python -class Pizza(object): - def __init__(self, ingredients): - self.ingredients = ingredients - - @classmethod - def from_fridge(cls, fridge): - return cls(fridge.get_cheese() + fridge.get_vegetables()) -``` - -Static methods calling static methods: if you split a static methods in several static methods, you shouldn't hard-code the class name but use class methods. Using this way to declare ou method, the Pizza name is never directly referenced and inheritance and method overriding will work flawlessly - -```python -class Pizza(object): - def __init__(self, radius, height): - self.radius = radius - self.height = height - - @staticmethod - def compute_area(radius): - return math.pi * (radius ** 2) - - @classmethod - def compute_volume(cls, height, radius): - return height * cls.compute_area(radius) - - def get_volume(self): - return self.compute_volume(self.height, self.radius) -``` - -### 1.3.7. Abstract methods - -An abstract method is a method defined in a base class, but that **may not provide any implementation**. In Java, it would describe the methods of an interface. -So the simplest way to write an abstract method in Python is: - -```python -class Pizza(object): - def get_radius(self): - raise NotImplementedError -``` - -Any class inheriting from Pizza should implement and override the get_radius method, otherwise an exception would be raised. -This particular way of implementing abstract method has a drawback. If you write a class that inherits from Pizza and forget to implement get_radius, the error will only be raised when you'll try to use that method. - -```python ->>> Pizza() -<__main__.Pizza object at 0x7fb747353d90> ->>> Pizza().get_radius() -Traceback (most recent call last): - File "", line 1, in - File "", line 3, in get_radius -NotImplementedError -``` -There's a way to triggers this way earlier, when the object is being instantiated, using the abc module that's provided with Python. - -```python -import abc - -class BasePizza(object): - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def get_radius(self): - """Method that should do something.""" -``` - -Using abc and its special class, as soon as you'll try to instantiate BasePizza or any class inheriting from it, you'll get a TypeError. - -```python ->>> BasePizza() -Traceback (most recent call last): - File "", line 1, in -TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius -``` - -### 1.3.8. Mixing static, class and abstract methods - -When building classes and inheritances, the time will come where you will have to mix all these methods decorators. So here's some tips about it. -Keep in mind that declaring a method as being abstract, doesn't freeze the prototype of that method. That means that it must be implemented, but i can be implemented with any argument list. - -```python -import abc - -class BasePizza(object): - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def get_ingredients(self): - """Returns the ingredient list.""" - -class Calzone(BasePizza): - def get_ingredients(self, with_egg=False): - egg = Egg() if with_egg else None - return self.ingredients + egg -``` - -This is valid, since Calzone fulfil the interface requirement we defined for BasePizza objects. That means that we could also implement it as being a class or a static method, for example: - -```python -import abc - -class BasePizza(object): - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def get_ingredients(self): - """Returns the ingredient list.""" - -class DietPizza(BasePizza): - @staticmethod - def get_ingredients(): - return None -``` - -This is also correct and fulfil the contract we have with our abstract BasePizza class. The fact that the get_ingredients method don't need to know about the object to return result is an implementation detail, not a criteria to have our contract fulfilled. - -Therefore, you can't force an implementation of your abstract method to be a regular, class or static method, and arguably you shouldn't. Starting with Python 3 (this won't work as you would expect in Python 2, see issue5867), it's now possible to use the @staticmethod and `@classmethod` decorators on top of @abstractmethod: - -```python -import abc - -class BasePizza(object): - __metaclass__ = abc.ABCMeta - - ingredient = ['cheese'] - - @classmethod - @abc.abstractmethod - def get_ingredients(cls): - """Returns the ingredient list.""" - return cls.ingredients -``` - -Don't misread this: if you think this going to force your subclasses to implement get_ingredients as a class method, you are wrong. This simply implies that your implementation of get_ingredients in the BasePizza class is a class method. - -An implementation in an abstract method? Yes! In Python, contrary to methods in Java interfaces, you can have code in your abstract methods and call it via `super()`: - -```python -import abc - -class BasePizza(object): - __metaclass__ = abc.ABCMeta - - default_ingredients = ['cheese'] - - @classmethod - @abc.abstractmethod - def get_ingredients(cls): - """Returns the ingredient list.""" - return cls.default_ingredients - -class DietPizza(BasePizza): - def get_ingredients(self): - return ['egg'] + super(DietPizza, self).get_ingredients() -``` - -In such a case, every pizza you will build by inheriting from BasePizza will have to override the get_ingredients method, but will be able to use the default mechanism to get the ingredient list by using super(). - -#### 1.3.8.1. Get in touch with me +#### :v: Get in touch with me > I am looking for Jobs ... :sunglasses: * [Github](https://github.com/avimehenwal/) * [My Website](https://avimehenwal.in) +* [My Blog v2](https://avimehenwal2.netlify.app/) * [Twitter Handle](https://twitter.com/avimehenwal) * [LinkedIn](https://in.linkedin.com/in/avimehenwal) * [Stackoverflow](https://stackoverflow.com/users/1915935/avi-mehenwal) diff --git a/docs/Tutorials/00_material.md b/docs/Tutorials/00_material.md index 1479ddb..99b9f30 100644 --- a/docs/Tutorials/00_material.md +++ b/docs/Tutorials/00_material.md @@ -43,30 +43,314 @@ stateDiagram-v2 Crash --> [*] ``` -::: quote alexander -Some quote please -::: +![Python programming logo](/logo.svg) -::: quote -horrible orrible hirriblksndoif iobni b -::: +::: theorem Principle of Science and Engineering +:cowboy_hat_face: Try to do ==good science== rather than :money_mouth_face: popular science. -::: theorem Newton's First Law -In an inertial frame of reference, an object either remains at rest or continues to move at a constant velocity, unless acted upon by a force. +Liberal Education +: Learn something about everything and everything about something. - ::: right - From [Wikipedia](https://en.wikipedia.org/wiki/Newton%27s_laws_of_motion) - ::: ::: -::: tip -Tip container of `@vuepress/theme-default` -::: -::: right -From [Wikipedia](https://en.wikipedia.org/wiki/Newton%27s_laws_of_motion) +# :bug: Pythonic + +- $Generators \subset Iterators$ All generators are iterators BUT not all iterators are generators +- Generators are usually attached to functions have `next()` method and `yield` +- Iterator creates a list generator generates ONE item at a time for computation + * Iterator *advantages* Creates item for computation one at a time and does not consumes more memory. +- Python supports + - Problem - cyclic dependency in case same method in both base classes + +```python +class Base1: + pass + +class Base2: + pass + +class MultiDerived(Base1, Base2): + pass + +class Base: + pass + +class Derived1(Base): + pass + +class Derived2(Derived1): + pass +``` + +## :lock: GIL - Global Interpreted Lock + +Python's GIL is intended to serialize access to interpreter internals from different threads. On multi-core systems, it means that multiple threads can't effectively make use of multiple cores. (If the GIL didn't lead to this problem, most people wouldn't care about the GIL - it's only being raised as an issue because of the increasing prevalence of multi-core systems.) +Note that Python's GIL is only really an issue for + +, the reference implementation. Jython and IronPython don't have a GIL. As a Python developer, you don't generally come across the GIL unless you're writing a C extension. C extension writers need to release the GIL when their extensions do blocking I/O, so that other threads in the Python process get a chance to run. + +## :unicorn: OOP - Object Oriented Programming + +### Python Operator Overloading + +Python operators work for built-in classes. But same operator behaves differently with different types. + +**For example,** the `+` operator will, perform arithmetic addition on two numbers, merge two lists and concatenate two strings. This feature in Python, that allows same operator to have different meaning according to the context is called operator overloading. + +### Polymorphism + +A common real example in Python is **file-like objects**. Besides actual files, several other types, including `StringIO` and `BytesIO`, are file-like. A method that acts as files can also act on them because they support the required methods (e.g. read, write). + +### Encapsulation (Accessibility) + +private attributes are defined by special syntax `self.__a` same with methods. +`def __methodName(self):` + +Major Difference between Python 2 and Python 3: + +1. print is now a function instead of keyword +2. xrange (iterable) is now replaced with range() +3. python 3 supports Unicode +4. raw_input() is replaced by input() method + +### Python Classes and Functions + +- New Classes and old classes. Difference ? +- Though classmethod and staticmethod are quite similar, there's a slight difference in usage for both entities: classmethod must have a reference to a class object as the first parameter, whereas staticmethod can have no parameters at all. +- Classmethods leads to Factory Design pattern in python + +### Python @staticmethod + +Static methods are a special case of methods. Sometimes, you'll write code that belongs to a class, but that doesn't use the object itself at all. For example: + +```python +class Pizza(object): + @staticmethod + def mix_ingredients(x, y): + return x + y + + def cook(self): + return self.mix_ingredients(self.cheese, self.vegetables) +``` + +In such a case, writing mix_ingredients as a non-static method would work too, but it would provide it a self argument that would not be used. Here, the decorator @staticmethod buys us several things: + +::: tip @staticmethod +Python doesn't have to instantiate a bound-method for each Pizza object we instantiate. +Bound methods are objects too, and creating them has a cost. Having a static method avoids that: ::: +```python +>>> Pizza().cook is Pizza().cook +False +>>> Pizza().mix_ingredients is Pizza.mix_ingredients +True +>>> Pizza().mix_ingredients is Pizza().mix_ingredients +True +``` + +It eases the readability of the code: seeing @staticmethod, we know that the method does not depend on the state of object itself; +It allows us to override the mix_ingredients method in a subclass. If we used a function mix_ingredients defined at the top-level of our module, a class inheriting from Pizza wouldn't be able to change the way we mix ingredients for our pizza without overriding cook itself. + +### Python @classmethods + +Having said that, what are class methods? Class methods are methods that are not bound to an object, but to… a class! + +```python +>>> class Pizza(object): +... radius = 42 +... @classmethod +... def get_radius(cls): +... return cls.radius +... +>>> +>>> Pizza.get_radius +> +>>> Pizza().get_radius +> +>>> Pizza.get_radius is Pizza().get_radius +True +>>> Pizza.get_radius() +42 +``` + +Whatever the way you use to access this method, it will be always bound to the class it is attached too, and its first argument will be the class itself (remember that classes are objects too). +When to use this kind of methods? Well class methods are mostly useful for two types of methods: +Factory methods, that are used to create an instance for a class using for example some sort of pre-processing. If we use a @staticmethod instead, we would have to hardcode the Pizza class name in our function, making any class inheriting from Pizza unable to use our factory for its own use. + +```python +class Pizza(object): + def __init__(self, ingredients): + self.ingredients = ingredients + + @classmethod + def from_fridge(cls, fridge): + return cls(fridge.get_cheese() + fridge.get_vegetables()) +``` + +Static methods calling static methods: if you split a static methods in several static methods, you shouldn't hard-code the class name but use class methods. Using this way to declare our method, the Pizza name is never directly referenced and inheritance and method overriding will work flawlessly + +```python +class Pizza(object): + def __init__(self, radius, height): + self.radius = radius + self.height = height + + @staticmethod + def compute_area(radius): + return math.pi * (radius ** 2) + + @classmethod + def compute_volume(cls, height, radius): + return height * cls.compute_area(radius) + + def get_volume(self): + return self.compute_volume(self.height, self.radius) +``` + +### Abstract methods + +An abstract method is a method defined in a base class, but that **may not provide any implementation**. In Java, it would describe the methods of an interface. +So the simplest way to write an abstract method in Python is: + +```python +class Pizza(object): + def get_radius(self): + raise NotImplementedError +``` + +Any class inheriting from Pizza should implement and override the get_radius method, otherwise an exception would be raised. +This particular way of implementing abstract method has a drawback. If you write a class that inherits from Pizza and forget to implement get_radius, the error will only be raised when you'll try to use that method. + +```python +>>> Pizza() +<__main__.Pizza object at 0x7fb747353d90> +>>> Pizza().get_radius() +Traceback (most recent call last): + File "", line 1, in + File "", line 3, in get_radius +NotImplementedError +``` +There's a way to triggers this way earlier, when the object is being instantiated, using the abc module that's provided with Python. + +```python +import abc + +class BasePizza(object): + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def get_radius(self): + """Method that should do something.""" +``` + +Using abc and its special class, as soon as you'll try to instantiate BasePizza or any class inheriting from it, you'll get a TypeError. + +```python +>>> BasePizza() +Traceback (most recent call last): + File "", line 1, in +TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius +``` + +### Mixing static, class and abstract methods + +When building classes and inheritances, the time will come where you will have to mix all these methods decorators. So here's some tips about it. +Keep in mind that declaring a method as being abstract, doesn't freeze the prototype of that method. That means that it must be implemented, but i can be implemented with any argument list. + +```python +import abc + +class BasePizza(object): + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def get_ingredients(self): + """Returns the ingredient list.""" + +class Calzone(BasePizza): + def get_ingredients(self, with_egg=False): + egg = Egg() if with_egg else None + return self.ingredients + egg +``` + +This is valid, since Calzone fulfil the interface requirement we defined for BasePizza objects. That means that we could also implement it as being a class or a static method, for example: + +```python +import abc + +class BasePizza(object): + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def get_ingredients(self): + """Returns the ingredient list.""" + +class DietPizza(BasePizza): + @staticmethod + def get_ingredients(): + return None +``` + +This is also correct and fulfill the contract we have with our abstract BasePizza class. The fact that the get_ingredients method don't need to know about the object to return result is an implementation detail, not a criteria to have our contract fulfilled. + +Therefore, you can't force an implementation of your abstract method to be a regular, class or static method, and arguably you shouldn't. Starting with Python 3 (this won't work as you would expect in Python 2, see issue5867), it's now possible to use the @staticmethod and `@classmethod` decorators on top of @abstractmethod: + +```python +import abc + +class BasePizza(object): + __metaclass__ = abc.ABCMeta + + ingredient = ['cheese'] + + @classmethod + @abc.abstractmethod + def get_ingredients(cls): + """Returns the ingredient list.""" + return cls.ingredients +``` + +Don't misread this: if you think this going to force your subclasses to implement get_ingredients as a class method, you are wrong. This simply implies that your implementation of get_ingredients in the BasePizza class is a class method. + +An implementation in an abstract method? Yes! In Python, contrary to methods in Java interfaces, you can have code in your abstract methods and call it via `super()`: + +```python +import abc + +class BasePizza(object): + __metaclass__ = abc.ABCMeta + + default_ingredients = ['cheese'] + + @classmethod + @abc.abstractmethod + def get_ingredients(cls): + """Returns the ingredient list.""" + return cls.default_ingredients + +class DietPizza(BasePizza): + def get_ingredients(self): + return ['egg'] + super(DietPizza, self).get_ingredients() +``` + +In such a case, every pizza you will build by inheriting from BasePizza will have to override the get_ingredients method, but will be able to use the default mechanism to get the ingredient list by using super(). + +