Alex Zaitsev
Alex Zaitsev

Reputation: 1781

python takes at most 2 arguments

I'm working on the simple strategy pattern implementation. I came to Python from Java world so I divided all classes to separate files as this seems ok for me. But I have troubles with packages and imports, please see the below code for details.

So I have a duck and 2 incapsulated behaviors: fly and quack.

Overall structure is:

behavior/
├── __init__.py
├── __init__.pyc
├── __pycache__
│   └── __init__.cpython-37.pyc
├── fly
│   ├── FlyBehavior.py
│   ├── FlyBehavior.pyc
│   ├── FlyNoWay.py
│   ├── FlyRocketPowered.py
│   ├── FlyRocketPowered.pyc
│   ├── FlyWithWings.py
│   ├── __init__.py
│   ├── __init__.pyc
│   └── __pycache__
│       ├── FlyBehavior.cpython-37.pyc
│       ├── FlyRocketPowered.cpython-37.pyc
│       └── __init__.cpython-37.pyc
└── quack
    ├── MuteQuack.py
    ├── Quack.py
    ├── QuackBehavior.py
    ├── Squeak.py
    └── __init__.py
duck
├── Duck.py
├── MallardDuck.py
├── ModelDuck.py
├── __init__.py
├── __init__.pyc
└── __pycache__
    ├── Duck.cpython-37.pyc
    ├── MallardDuck.cpython-37.pyc
    └── __init__.cpython-37.pyc
MiniDuckSimulator.py
MiniDuckSimulator.pyc

Fly classes:

FlyBehavior.py

from abc import ABC, abstractmethod

class FlyBehavior(ABC):

    @abstractmethod
    def fly(self):
        pass

FlyNoWay.py

from behavior.fly import FlyBehavior

class FlyNoWay(FlyBehavior):

    def fly(self):
        print("I can't fly")

FlyRocketPowered.py

from behavior.fly import FlyBehavior

class FlyRocketPowered(FlyBehavior):

    def fly(self):
        print("I'm flying with a rocket")

FlyWithWings.py

from behavior.fly import FlyBehavior

class FlyWithWings(FlyBehavior):

    def fly(self):
        print("I'm flying!")

Quack classes:

QuackBehavior.py

from abc import ABC, abstractmethod

class QuackBehavior(ABC):

    @abstractmethod
    def quack(self):
        pass

Quack.py

from behavior.quack import QuackBehavior

class Quack(QuackBehavior):

    def quack(self):
        print('Quack')

MuteQuack.py

from behavior.quack import QuackBehavior

class MuteQuack(QuackBehavior):

    def quack(self):
        print('<< Silence >>')

Squeak.py

from behavior.quack import QuackBehavior

class Squeak(QuackBehavior):

    def quack(self):
        print('Squeak')

Duck classes:

Duck.py

from abc import ABC, abstractmethod

class Duck(ABC):

    fly_behavior = None
    quack_behavior = None

    @abstractmethod
    def display(self):
        pass

    def perform_fly(self):
        self.fly_behavior.fly()

    def perform_quack(self):
        self.quack_behavior.quack()

    def swim(self):
        print('All ducks float, even decoys!')

MallardDuck.py

from duck import Duck

class MallardDuck(Duck):

    def __init__(self):
        self.quack_behavior = Quack()
        self.fly_behavior = FlyWithWings()

    def display(self):
        print("I'm a real Mallard duck")

ModelDuck.py

from duck import Duck

class ModelDuck(Duck):

    def __init__(self):
        self.fly_behavior = FlyNoWay()
        self.quack_behavior = Quack()

    def display(self):
        print("I'm a model duck")

And main class:

MiniDuckSimulator.py

from duck import MallardDuck
from duck import ModelDuck
import behavior.fly.FlyRocketPowered as FlyRocketPowered

if __name__ == "__main__":
    mallard = MallardDuck()
    mallard.display()
    mallard.perform_fly()
    mallard.perform_quack()

    model = ModelDuck()
    model.display()
    model.perform_fly()
    model.fly_behavior = FlyRocketPowered()
    model.perform_fly()

Program output:

$ python MiniDuckSimulator.py 
Traceback (most recent call last):
  File "MiniDuckSimulator.py", line 1, in <module>
    from duck import MallardDuck
  File "/Users/p/Documents/Develop/patterns_book/00_strategy/py/duck/MallardDuck.py", line 3, in <module>
    class MallardDuck(Duck):
TypeError: module() takes at most 2 arguments (3 given)

What's wrong with my modules? Is my approach for storing and structuring code/classes ok? Thanks.

Upvotes: 0

Views: 74

Answers (1)

blue note
blue note

Reputation: 29099

It should be

from duck.MallardDuck import MallardDuck

The MallardDuck you are importing is still a file, not a class, even though it has a single class in it.

Change all of your other imports in a similar manner.

some notes:

  • strategy pattern is kind of useless in python, you can pass a function directly as an argument, instead of wrapping it in a class
  • there's no reason to have a single class per file, use files to group relevant classes according to your judjement
  • by convention, module (file) names are all lowercase, class names only are camelcase

Upvotes: 4

Related Questions