two classes with similar attributes except one of the attributes is different - python

class Air:
def __init__(self,supplier,delivery,ensurance):
self.supplier = supplier
self.delivery = delivery
self.ensurance = ensurance
def rate_for_custom(self):
return (self.supplier + self.delivery + self.ensurance)
class Sea:
def __init__(self,supplier,delivery,ensurance,port_tax):
self.supplier = supplier
self.delivery = delivery
self.ensurance = ensurance
self.port_tax = port_tax
def rate_for_custom(self):
return (self.supplier + self.delivery + self.ensurance + self.port_tax)
so i'm trying to write a program that calculates the import taxes in israel.
There are two types: one in the sea and one in the air
they both share the same attributes except Sea needs to be calculated with another attribute.
I'm feeling like my code is not good(i'm new to pragramming started a week ago)
is it fine to use two classes in this case? if not what is the solution (by stil using OOP because I need to practice with it)

You can move common parts to a common parent class:
class Transport:
def __init__(self,supplier,delivery,ensurance):
self.supplier = supplier
self.delivery = delivery
self.ensurance = ensurance
def rate_for_custom(self):
return (self.supplier + self.delivery + self.ensurance)
class Air(Transport):
pass
class Sea(Transport):
def __init__(self,supplier,delivery,ensurance,port_tax):
super().__init__(supplier, delivery, ensurance)
self.port_tax = port_tax
def rate_for_custom(self):
return super().rate_for_custom() + self.port_tax

As you want to learn OOP, then you can start to see the concept of inheritance. Here is an example:
# generic class
class Custom:
def __init__(self,*args):
# collect all given parameters:
self.args = args
def rate_for_custom(self):
# just sum all numbers in given parameter:
return sum(self.args)
class Sea(Custom):
def __init__(self,supplier=0,delivery=0,insurance=0, port_tax = 0):
# Call Custom class and provide all relevant parameters:
super().__init__(supplier, delivery, insurance, port_tax)
class Air(Custom):
def __init__(self,supplier=0, delivery=0, insurance=0):
# Call Custom class and provide all relevant parameters:
super().__init__(supplier, delivery, insurance )
print(Custom(100,50,25).rate_for_custom())
# 175
print(Air(supplier=100,delivery=50,insurance=25).rate_for_custom())
# 175
print(Sea(supplier=100,delivery=50,insurance=25,port_tax=25).rate_for_custom())
# 200
Customclass is doing all the job, by summing all parameters it receives in init(). You can call this class providing the values to sum :Custom(100,50,25).rate_for_custom()
Two other classes Airand Sea are inheriting from the Customclass and are just an interface. Using them allows you to use keyword arguments instead of simple arguments: Sea(supplier=100,delivery=50,insurance=25,port_tax=25) which is more friendly.

Related

Decoding JSON dump as object

I am doing my college assignment and one of the things my lecture is looking for is encoding an object and dumping it as JSON, decoding it then loading it into the PassengerFlight class.
When I run the code it keeps showing
'PassengerFlight' object has no attribute 'airlineName'
When I decode it, VSCode is showing it has all the set function variables. The only class I can get it to run in is the Flight class when I remove the abstract method. Is there any way to run it within the PassengerFlight class and not show the above error?
from abc import ABC, abstractmethod
import json
from json import JSONEncoder
class Flight(ABC, object): # Flight Class (MAIN)
def __init__(self, airlineName, departureAirport, arrivalAirport): # Constructor Method
self.airlineName: str # Declaring attributes & Setting Types
self.departureAirport: str # Declaring attributes & Setting Types
self.arrivalAirport: str # Declaring attributes & Setting Types
def setAirlineName(self, airlineName): # Mutator Method
self.airlineName = airlineName
#abstractmethod # Marking this methods as abstract method, any concrete subclass will have to implement this method
def getPrice(self):
pass
def setDepartureAirport(self, departureAirport): # Mutator Method
self.departureAirport = departureAirport
def getDepartureAirport(self): # Accessor Method
if len(self.departureAirport) > 0: # Error Checking
return self.departureAirport
else:
return "No departure airport set"
def setArrivalAirport(self, arrivalAirport): # Mutator Method
self.arrivalAirport = arrivalAirport
def getArrivalAirport(self): # Accessor Method
if len(self.arrivalAirport) > 0: # Error Checking
return self.arrivalAirport
else:
return "No arrival airport set"
def __eq__(self, otherFlight):
return (self.airlineName == otherFlight.airlineName)
def __str__(self): # Overiding Method
return "\n==================================================\n++++++++++++++++++ Flight Info ++++++++++++++++++\n==================================================\nAirline Name: " + self.airlineName + "\Departure Airport: " + self.departureAirport + "\nArrival Airport: " + self.arrivalAirport
class PassengerFlight(Flight, object): # PassengerFlight Class (EXTENDS MAIN)
def __init__(self, airlineName, departureAirport, arrivalAirport, price, redEye, passengerList, flightType, baggageWeight): # Constructor Method
super().__init__(airlineName, departureAirport, arrivalAirport)
self.passengerList: list # Declaring attributes & Setting Types
self.flightType: str # Declaring attributes & Setting Types
self.baggageWeight: float # Declaring attributes & Setting Types
self.price: float # Declaring attributes & Setting Types
self.redEye: bool
def getAirlineName(self): # Accessor Method
if len(self.airlineName) > 0: # Error Checking
return self.airlineName
else:
return "No airline name set"
def setRedEye(self, redEye):
self.redEye = redEye
def isRedEye(self):
if self.redEye == True:
return "Flight is red eye"
else:
return "Flight is not a red eye"
def setPassengerName(self, passengerList): # Mutator Method
self.passengerList = passengerList
def getPassengerName(self): # Accessor Method
if len(self.passengerList) > 0: # Error Checking
self.passengerList.sort()
return self.passengerList
else:
return "Passenger List Not Set"
def setFlightType(self, flightType): # Mutator Method
self.flightType = flightType
def getFlightType(self): # Accessor Method
if len(self.flightType) > 0: # Error Checking
return self.flightType
else:
return "No Flight Type Set"
def setBaggageWeight(self): # Mutator Method
baggageWeight = 0
for i in range(len(self.passengerList)): # Iterates through passenger list
baggageWeight += 50.00 # For each passenger in the list add 50KG to baggage variable
self.baggageWeight = baggageWeight # Set our attribute equal to the variable
def getBaggageWeight(self): # Accessor Method
if self.baggageWeight == 0:
return "No Baggage Weight Set"
else:
return self.baggageWeight
def setPrice(self, price):
self.price = price * len(self.passengerList)
def getPrice(self):
if self.price != 0:
return self.price
else:
return "Price is not set"
def sortedNames(self):
return sorted(self.passengerList)
def __str__(self): # Overiding Method
return super().__str__() + "\nPassenger Names using sort(): " + str(self.getPassengerName()) + "\nFlight Type: " + self.flightType + "\nBaggage Weight: " + str(self.baggageWeight) + '(KG)\n' + "Money earned for this flight is: " + str(self.getPrice()) + "\nPassenger Names using Sorted(): " + str(self.sortedNames()) + '\n==================================================\n'
class FlightEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
##########################################################
# Calling PassengerFlight Class #
##########################################################
# Initialize Class & Set to Variable
passenger = PassengerFlight(None, None, None, None, None, None, None, None)
passenger.setAirlineName('Aer Lingus') # Set mutators & values
passenger.setArrivalAirport('Chicago O\'Hare Intl') # Set mutators & values
passenger.setDepartureAirport('Dublin') # Set mutators & values
passenger.setRedEye(True)
passenger.setFlightType('Long Haul') # Set mutators & values
passenger.setPassengerName(
['Andrew Check', 'Graham Whitaker', 'John Eire', 'Vicky Bunsworth', 'Lorna Lopsworth']) # Set mutators & values
passenger.setBaggageWeight() # Set mutators & values
passenger.setPrice(200.00)
# uses the overridden _str_ method to print detail of the class
print(passenger)
##########################################################
passengerEncode = json.dumps(passenger, cls=FlightEncoder, indent=4)
passengerDecode = json.loads(passengerEncode)
passengerObj = PassengerFlight(**passengerDecode)
print(passengerObj)
Hint
def __str__(self): # Overiding Method
return (
super().__str__()
+ "\nPassenger Names using sort(): "
+ str(self.getPassengerName())
+ "\nFlight Type: "
+ self.flightType
+ "\nBaggage Weight: "
+ str(self.baggageWeight)
+ "(KG)\n"
+ "Money earned for this flight is: "
+ str(self.getPrice())
+ "\nPassenger Names using Sorted(): "
+ str(self.sortedNames())
+ "\n==================================================\n"
)
You call super().__str__(). self is an instance of PassengerFlight which inherited from Flight. super() means: "call a method defined in the parent class next in __mro__". Flight doesn't have the attribute.
super
The super() function is used to give access to methods and properties of a parent or sibling class. The super() function returns an object that represents the parent class.
OOP
Using child class attributes in the parent class breaks the "Dependency Inversion Principle" (SOLID).
In object-oriented design, a dependency inversion principle is a specific form of decoupling software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details.
High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces).
Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.
Your abstraction depends on the higher-level implementation.
Solution
from abc import ABCMeta, abstractproperty
class Flight(metaclass=ABCMeta):
#abstractproperty
def airLineName(self):
raise NotImplementedError()
With the property declared in the abstraction you have to implement it in the child types. Based on this you can use the abstract properties in the abstraction without errors and risks to call not implemented attribute. Also, it satisfies SOLID principles.

How to call a function when instances are being dynamically created?

I'm a Java newbie, transitioning into Python and I've been trying to develop a simplistic market-like interaction between companies and investors. Basically, there are 100 companies and 100 investors been created dynamically with random values at initialization.
class Company:
def __init__(self):
""" Constructor for the Company object """
self.id: str = uuid.uuid4().hex
self.shares_num = random.randint(500, 1000)
self.share_price = Decimal(random.randint(10, 100))
class Investor:
def __init__(self):
""" Constructor for the Investor object """
self.id_inv: str = uuid.uuid1().hex
self.budget: Decimal = random.randint(50_000, 100_000)
self.acq_shares = 0
def sell_shares(self):
trade = self.budget - Company.get_share_price
Company.get_shares_num -= 1
self.acq_shares += 1
self.set_budget = trade
return self
The function sell_shares() performs the actual sale, i.e. makes the trade between the investor's money and the company's shares.
The companies and investors are then placed into a list with their ID and a dict with share's data for companies and budget's for investors.
# dynamic instances of Companies and Investors
comp = [Company() for _ in range(10)]
companies = {c.id: c for c in comp}
inv = [Investor() for _ in range(10)]
investors = {i.id_inv: i for i in inv}
The problem is when I call the sell_shares() method Investors.sell_shares neither the instances of companies or shares are affected. I don't really see anything wrong, apart from the fact that it isn't working.
Any suggestions on how I could try and fix this?
Thanks a million :)
P.S.: I'm using Python 3.8.2 with standard libraries.
Probably the biggest source of your pain is your use of mutable global variables inside of a class method. Please don't do that. Every time you do, somewhere, a baby kitten dies.
You could fix this problem quite easily by making trade() accept a keyword argument for a company, and then just operate using self (referring to that particular investor), and the keyword argument, (referring to a particular instance of a company). Don't try to access all the investors and companies at once, being that your method only depends on one of each.
import uuid
import random
from decimal import Decimal
class Company:
def __init__(self):
""" Constructor for the Company object """
self.id: str = uuid.uuid4().hex
self.shares_num = random.randint(500, 1000)
self.share_price = Decimal(random.randint(10, 100))
class Investor:
def __init__(self):
""" Constructor for the Investor object """
self.id: str = uuid.uuid1().hex
self.budget: Decimal = random.randint(50000, 100000)
self.acq_shares = 0
def trade(self, company):
trading = self.budget - company.share_price
company.share_price -= 1
self.acq_shares += 1
# this equation is wrong, but I'm not sure entirely what you want to do here
# this is equivalent to -company.share_price
company.share_price = trading - self.budget
self.budget = trading
return self.id, self.budget
Note that this also removes any need to create get_share_price() or get_budget() methods.
If, somehow, I've misunderstood your setup, and your trade function does depend on all investors and all companies at once, then don't make it a class method. Make it a regular function, outside of a class, where it takes two arguments like so def trade(investors, companies):, because in that case, it doesn't have to do with that single class instance of investor.
You can test out your classes like so:
# Generate companies and investors
comp = [Company() for _ in range(10)]
companies = {c.id: c for c in comp} # <-- not sure what this is used for
inv = [Investor() for _ in range(10)]
investors = {i.id: i for i in inv} # <-- not sure what this is used for
# Select an investor and a company
some_investor = inv[random.randint(0,9)]
some_company = comp[random.randint(0,9)]
# Make a trade
some_investor.trade(some_company)
print(some_company.share_price) # prints a negative number
Note that your current formula for share price seems very wrong to me, being that it's equivalent to self.budget - company.share_price - self.budget.
Hope this helps.

Manager / Container class, how to?

I am currently designing a software which needs to manage a certain hardware setup.
The hardware setup is as following :
System - The system contains two identical devices, and has certain functionality relative to the entire system.
Device - Each device contains two identical sub devices, and has certain functionality relative to both sub devices.
Sub device - Each sub device has 4 configurable entities (Controlled via the same hardware command - thus I don't count them as a sub-sub device).
What I want to achieve :
I want to control all configurable entities via the system manager (the entities are counted in a serial way), meaning I would be able to do the following :
system_instance = system_manager_class(some_params)
system_instance.some_func(0) # configure device_manager[0].sub_device_manager[0].entity[0]
system_instance.some_func(5) # configure device_manager[0].sub_device_manager[1].entity[1]
system_instance.some_func(8) # configure device_manager[1].sub_device_manager[1].entity[0]
What I have thought of doing :
I was thinking of creating an abstract class, which contains all sub device functions (with a call to a conversion function) and have the system_manager, device_manager and sub_device_manager inherit it. Thus all classes will have the same function name and I will be able to access them via the system manager.
Something around these lines :
class abs_sub_device():
#staticmethod
def convert_entity(self):
sub_manager = None
sub_entity_num = None
pass
def set_entity_to_2(entity_num):
sub_manager, sub_manager_entity_num = self.convert_entity(entity_num)
sub_manager.some_func(sub_manager_entity_num)
class system_manager(abs_sub_device):
def __init__(self):
self.device_manager_list = [] # Initiliaze device list
self.device_manager_list.append(device_manager())
self.device_manager_list.append(device_manager())
def convert_entity(self, entity_num):
relevant_device_manager = self.device_manager_list[entity_num // 4]
relevant_entity = entity_num % 4
return relevant_device_manage, relevant_entity
class device_manager(abs_sub_device):
def __init__(self):
self.sub_device_manager_list = [] # Initiliaze sub device list
self.sub_device_manager_list.append(sub_device_manager())
self.sub_device_manager_list.append(sub_device_manager())
def convert_entity(self, entity_num):
relevant_sub_device_manager = self.sub_device_manager_list[entity_num // 4]
relevant_entity = entity_num % 4
return relevant_sub_device_manager, relevant_entity
class sub_device_manager(abs_sub_device):
def __init__(self):
self.entity_list = [0] * 4
def set_entity_to_2(self, entity_num):
self.entity_list[entity_num] = 2
The code is for generic understanding of my design, not for actual functionality.
The problem :
It seems to me that the system I am trying to design is really generic and that there must be a built-in python way to do this, or that my entire object oriented look at it is wrong.
I would really like to know if some one has a better way of doing this.
After much thinking, I think I found a pretty generic way to solve the issue, using a combination of decorators, inheritance and dynamic function creation.
The main idea is as following :
1) Each layer dynamically creates all sub layer relevant functions for it self (Inside the init function, using a decorator on the init function)
2) Each function created dynamically converts the entity value according to a convert function (which is a static function of the abs_container_class), and calls the lowers layer function with the same name (see make_convert_function_method).
3) This basically causes all sub layer function to be implemented on the higher level with zero code duplication.
def get_relevant_class_method_list(class_instance):
method_list = [func for func in dir(class_instance) if callable(getattr(class_instance, func)) and not func.startswith("__") and not func.startswith("_")]
return method_list
def make_convert_function_method(name):
def _method(self, entity_num, *args):
sub_manager, sub_manager_entity_num = self._convert_entity(entity_num)
function_to_call = getattr(sub_manager, name)
function_to_call(sub_manager_entity_num, *args)
return _method
def container_class_init_decorator(function_object):
def new_init_function(self, *args):
# Call the init function :
function_object(self, *args)
# Get all relevant methods (Of one sub class is enough)
method_list = get_relevant_class_method_list(self.container_list[0])
# Dynamically create all sub layer functions :
for method_name in method_list:
_method = make_convert_function_method(method_name)
setattr(type(self), method_name, _method)
return new_init_function
class abs_container_class():
#staticmethod
def _convert_entity(self):
sub_manager = None
sub_entity_num = None
pass
class system_manager(abs_container_class):
#container_class_init_decorator
def __init__(self):
self.device_manager_list = [] # Initiliaze device list
self.device_manager_list.append(device_manager())
self.device_manager_list.append(device_manager())
self.container_list = self.device_manager_list
def _convert_entity(self, entity_num):
relevant_device_manager = self.device_manager_list[entity_num // 4]
relevant_entity = entity_num % 4
return relevant_device_manager, relevant_entity
class device_manager(abs_container_class):
#container_class_init_decorator
def __init__(self):
self.sub_device_manager_list = [] # Initiliaze sub device list
self.sub_device_manager_list.append(sub_device_manager())
self.sub_device_manager_list.append(sub_device_manager())
self.container_list = self.sub_device_manager_list
def _convert_entity(self, entity_num):
relevant_sub_device_manager = self.sub_device_manager_list[entity_num // 4]
relevant_entity = entity_num % 4
return relevant_sub_device_manager, relevant_entity
class sub_device_manager():
def __init__(self):
self.entity_list = [0] * 4
def set_entity_to_value(self, entity_num, required_value):
self.entity_list[entity_num] = required_value
print("I set the entity to : {}".format(required_value))
# This is used for auto completion purposes (Using pep convention)
class auto_complete_class(system_manager, device_manager, sub_device_manager):
pass
system_instance = system_manager() # type: auto_complete_class
system_instance.set_entity_to_value(0, 3)
There is still a little issue with this solution, auto-completion would not work since the highest level class has almost no static implemented function.
In order to solve this I cheated a bit, I created an empty class which inherited from all layers and stated to the IDE using pep convention that it is the type of the instance being created (# type: auto_complete_class).
Does this solve your Problem?
class EndDevice:
def __init__(self, entities_num):
self.entities = list(range(entities_num))
#property
def count_entities(self):
return len(self.entities)
def get_entity(self, i):
return str(i)
class Device:
def __init__(self, sub_devices):
self.sub_devices = sub_devices
#property
def count_entities(self):
return sum(sd.count_entities for sd in self.sub_devices)
def get_entity(self, i):
c = 0
for index, sd in enumerate(self.sub_devices):
if c <= i < sd.count_entities + c:
return str(index) + " " + sd.get_entity(i - c)
c += sd.count_entities
raise IndexError(i)
SystemManager = Device # Are the exact same. This also means you can stack that infinite
sub_devices1 = [EndDevice(4) for _ in range(2)]
sub_devices2 = [EndDevice(4) for _ in range(2)]
system_manager = SystemManager([Device(sub_devices1), Device(sub_devices2)])
print(system_manager.get_entity(0))
print(system_manager.get_entity(5))
print(system_manager.get_entity(15))
I can't think of a better way to do this than OOP, but inheritance will only give you one set of low-level functions for the system manager, so it wil be like having one device manager and one sub-device manager. A better thing to do will be, a bit like tkinter widgets, to have one system manager and initialise all the other managers like children in a tree, so:
system = SystemManager()
device1 = DeviceManager(system)
subDevice1 = SubDeviceManager(device1)
device2 = DeviceManager(system)
subDevice2 = SubDeviceManager(device2)
#to execute some_func on subDevice1
system.some_func(0, 0, *someParams)
We can do this by keeping a list of 'children' of the higher-level managers and having functions which reference the children.
class SystemManager:
def __init__(self):
self.children = []
def some_func(self, child, *params):
self.children[child].some_func(*params)
class DeviceManager:
def __init__(self, parent):
parent.children.append(self)
self.children = []
def some_func(self, child, *params):
self.children[child].some_func(*params)
class SubDeviceManager:
def __init__(self, parent):
parent.children.append(self)
#this may or may not have sub-objects, if it does we need to make it its own children list.
def some_func(self, *params):
#do some important stuff
Unfortunately, this does mean that if we want to call a function of a sub-device manager from the system manager without having lots of dots, we will have to define it again again in the system manager. What you can do instead is use the built-in exec() function, which will take in a string input and run it using the Python interpreter:
class SystemManager:
...
def execute(self, child, function, *args):
exec("self.children[child]."+function+"(*args)")
(and keep the device manager the same)
You would then write in the main program:
system.execute(0, "some_func", 0, *someArgs)
Which would call
device1.some_func(0, someArgs)
Here's what I'm thinking:
SystemManager().apply_to_entity(entity_num=7, lambda e: e.value = 2)
class EntitySuperManagerMixin():
"""Mixin to handle logic for managing entity managers."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # Supports any kind of __init__ call.
self._entity_manager_list = []
def apply_to_entity(self, entity_num, action):
relevant_entity_manager = self._entity_manager_list[index // 4]
relevant_entity_num = index % 4
return relevant_entity_manager.apply_to_entity(
relevant_entity_num, action)
class SystemManager(EntitySuperManagerMixin):
def __init__(self):
super().__init__()
# An alias for _entity_manager_list to improve readability.
self.device_manager_list = self._entity_manager_list
self.device_manager_list.extend(DeviceManager() for _ in range(4))
class DeviceManager(EntitySuperManagerMixin):
def __init__(self):
super().__init__()
# An alias for _entity_manager_list to improve readability.
self.sub_device_manager_list = self._entity_manager_list
self.sub_device_manager_list.extend(SubDeviceManager() for _ in range(4))
class SubDeviceManager():
"""Manages entities, not entity managers, thus doesn't inherit the mixin."""
def __init__(self):
# Entities need to be classes for this idea to work.
self._entity_list = [Entity() for _ in range(4)]
def apply_to_entity(self, entity_num, action):
return action(self._entity_list[entity_num])
class Entity():
def __init__(self, initial_value=0):
self.value = initial_value
With this structure:
Entity-specific functions can stay bound to the Entity class (where it belongs).
Manager-specific code needs to be updated in two places: EntitySuperManagerMixin and the lowest level manager (which would need custom behavior anyway since it deals with the actual entities, not other managers).
The way i see it if you want to dynamically configure different part of system you need some sort of addressing so if you input an ID or address with some parameter the system will know with address on which sub sistem you are talking about and then configure that system with parameter.
OOP is quite ok for that and then you can easily manipulate such data via bitwise operators.
So basic addressing is done via binary system , so to do that in python you need first to implement an address static attribute to your class with perhaps some basic further detailing if system grows.
Basic implementation of addres systems is as follows:
bin(71)
1010 1011
and if we divide it into nibbles
1010 - device manager 10
1011 - sub device manager 11
So in this example we have system of 15 device managers and 15 sub device menagers, and every device and sub device manager has its integer address.So let's say you want to access device manager no10 with sub device manager no11. You would need their address which is in binary 71 and you would go with:
system.config(address, parameter )
Where system.config funcion would look like this:
def config(self,address, parameter):
device_manager = (address&0xF0)>>4 #10
sub_device_manager = address&0xf # 11
if device_manager not in range(self.devices): raise LookupError("device manager not found")
if sub_device_manager not in range(self.devices[device_manager].device): raise LookupError("sub device manager not found")
self.devices[device_manager].device[sub_device_manager].implement(parameter)
In layman you would tell system that sub_device 11 from device 10 needs configuration with this parameter.
So how would this setup look in python inheritance class of some base class of system that could be then composited/inherited to different classes:
class systems(object):
parent = None #global parent element, defaults to None well for simplicity
def __init__(self):
self.addrMASK = 0xf # address mask for that nibble
self.addr = 0x1 # default address of that element
self.devices = [] # list of instances of device
self.data = { #some arbitrary data
"param1":"param_val",
"param2":"param_val",
"param3":"param_val",
}
def addSubSystem(self,sub_system): # connects elements to eachother
# checks for valiability
if not isinstance(sub_system,systems):
raise TypeError("defined input is not a system type") # to prevent passing an integer or something
# appends a device to system data
self.devices.append(sub_system)
# search parent variables from sub device manager to system
obj = self
while 1:
if obj.parent is not None:
obj.parent.addrMASK<<=4 #bitshifts 4 bits
obj.parent.addr <<=4 #bitshifts 4 bits
obj = obj.parent
else:break
#self management , i am lazy guy so i added this part so i wouldn't have to reset addresses manualy
self.addrMASK <<=4 #bitshifts 4 bits
self.addr <<=4 #bitshifts 4 bits
# this element is added so the obj address is coresponding to place in list, this could be done more eloquently but i didn't know what are your limitations
if not self.devices:
self.devices[ len(self.devices)-1 ].addr +=1
self.devices[ len(self.devices)-1 ].parent = self
# helpful for checking data ... gives the address of system
def __repr__(self):
return "system at {0:X}, {1:0X}".format(self.addr,self.addrMASK)
# extra helpful lists data as well
def __str__(self):
data = [ '{} : {}\n'.format(k,v) for k,v in self.data.items() ]
return " ".join([ repr(self),'\n',*data ])
#checking for data, skips looping over sub systems
def __contains__(self,system_index):
return system_index-1 in range(len(self.data))
# applying parameter change -- just an example
def apply(self,par_dict):
if not isinstance(par_dict,dict):
raise TypeError("parameter must be a dict type")
if any( key in self.data.keys() for key in par_dict.keys() ):
for k,v in par_dict.items():
if k in self.data.keys():
self.data[k]=v
else:pass
else:pass
# implementing parameters trough addresses
def implement(self,address,parameter_dictionary):
if address&self.addrMASK==self.addr:
if address-self.addr!=0:
item = (address-self.addr)>>4
self.devices[item-1].implement( address-self.addr,parameter_dictionary )
else:
self.apply(parameter_dictionary)
a = systems()
b = systems()
a.addSubSystem(b)
c = systems()
b.addSubSystem(c)
print('a')
print(a)
print('')
print('b')
print(b)
print('')
print('c')
print(c)
print('')
a.implement(0x100,{"param1":"a"})
a.implement(0x110,{"param1":"b"})
a.implement(0x111,{"param1":"c"})
print('a')
print(a)
print('')
print('b')
print(b)
print('')
print('c')
print(c)
print('')

Pass enum type as constructor argument

I am new to python and I would like to pass an enum as an argument to a constructor, within a function.
EDIT: I am working on a program with a class that has to organize different types of data, but most of these data types can be treated the same way. This data won't be all be added at the same time or in a foreseeable order. I would therefore like to keep the same functions, and just change the way the constructor stores the data. Let's consider this simpler example:
Say I have an enum
from enum import Enum, auto
class HouseThing(Enum):
people = auto()
pets = auto()
furniture = auto()
And I have a class House that can contain some or all of those things
class House():
def __init__(self, address, people = None, pets = None,
furniture = None):
self.address = address,
if self.people is not None:
self.people = people
etc....
And now I want to have a function that makes new furbished houses, but I want to use a function that could be used for any house:
house_things = HouseThing.furniture
def make_house_with_some_house_things(neighborhood, house_things):
neighborhood.append(House(house_things.name = house_things.name))
Is there a way to do this without first testing what kind of HouseThing house_things is first? house_things.name passes a string, but I would like it to be able to use it as a keyword.
I'm not sure exactly what you are trying to achieve here, but for the sake of solving the puzzle:
First, change House to determine what it has been passed:
class House():
def __init__(self, address, *house_things):
self.address = address
for ht in house_things:
if ht is HouseThings.people:
self.people = ht
elif ht is HouseThings.pets:
self.pets = ht
elif ht is HouseThings.furniture:
self.furniture = ht
else:
raise ValueError('unknown house thing: %r' % (ht, ))
Then, change make_house_with_some_house_things to just pass the house things it was given:
def make_house_with_some_house_things(neighborhood, house_things):
neighborhood.append(House(house_things))

calling a method inside a class-Python

class Time:
def __init__(self,x,y,z):
self.hour=x
self.minute=y
self.second=z
def __str__(self):
return "({:02d}:{:02d}:{:02d})".format(self.hour, self.minute, self.second)
def time_to_int(time):
minutes=time.hour*60+time.minute
seconds=minutes*60+time.second
return seconds
def int_to_time(seconds):
time=Time()
minutes,time.second=divmod(seconds,60)
time.hour,time.minute=divmod(minutes,60)
return time
def add_time(t1,t2):
seconds=time_to_int(t1)+time_to_int(t2)
return int_to_time(seconds)
start=Time(9,45,00)
running=Time(1,35,00)
done=add_time(start,running)
print(done)
I am new to python and i've been doing some practice lately.I came across a question and i've written the code for the same.But I am repeatedly getting an error: "add_time is not defined". I tried defining a main() method but then it doesn't print anything.Please help.
You haven't created an object to the above class.
Any function/method inside a class can only be accessed by an object of that class .For more information on the fundamentals of Object Oriented Programming, please check this page.
Meanwhile for this to work, define your class in the following way :
class Time:
def __init__(self,x=None,y=None,z=None):
self.hour=x
self.minute=y
self.second=z
def __str__(self):
return "({:02d}:{:02d}:{:02d})".format(self.hour, self.minute, self.second)
def time_to_int(time):
minutes=time.hour*60+time.minute
seconds=minutes*60+time.second
return seconds
def int_to_time(seconds):
time=Time()
minutes,time.second=divmod(seconds,60)
time.hour,time.minute=divmod(minutes,60)
return time
def add_time(t1,t2):
seconds=time_to_int(t1)+time_to_int(t2)
return int_to_time(seconds)
and outside the class block, write the following lines :
TimeObject = Time()
start=Time(9,45,00)
running=Time(1,35,00)
TimeObject.add_time(start,running)
print "done"
I however suggest you to write the add_time function outside the class because you are passing the objects to the class as the parameters to the function within the same class and it is considered as a bad design in object oriented programming.
Hope it helps. Cheers!
This works fine for me as long as you specified 3 args in your constructor
def int_to_time(seconds):
time=Time(0,0,0) # just set your 3 positionals args here
minutes,time.second=divmod(seconds,60)
time.hour,time.minute=divmod(minutes,60)
return time
Another way to avoid it could be:
class Time:
def __init__(self,x=0,y=0,z=0):
self.hour=x
self.minute=y
self.second=z
If you want to add your functions to your class (such as time_to_int, int_to_time or even add_time) then you will need to indent with one more level of 4 spaces and add self to your method parameters
Hii Mathers25,
I solve your problem try this below code to get the best output,
class TimeClass:
def __init__(self,x,y,z):
self.hour = x
self.minute = y
self.second = z
def __str__(self):
return "({:02d}:{:02d}:{:02d})".format(self.hour, self.minute, self.second)
def time_to_int(self,time):
minutes = (time.hour * 60) + time.minute
seconds = (minutes * 60) + time.second
return seconds
def int_to_time(self,seconds):
time = TimeClass(0,0,0)
minutes,time.second=divmod(seconds,60)
time.hour,time.minute=divmod(minutes,60)
return time
def add_time(self,t1,t2):
seconds = self.time_to_int(t1) + self.time_to_int(t2)
# Call method int_to_time() using self keyword.
return self.int_to_time(seconds)
# First time object create that time set value is 0 of hour,minute and second
TimeObject = TimeClass(0,0,0)
# After create second object
start=TimeClass(9,45,00)
# After create thired Object
running=TimeClass(1,35,00)
# Store the value which return by add_time()
done = TimeObject.add_time(start,running)
# Display the value of done variable
print(done)
class Employee:
def __init__(self):
self.wage = 0
self.hours_worked = 0
def calculate_pay(self):
return self.wage * self.hours_worked
alice = Employee()
alice.wage = 9.25
alice.hours_worked = 35
print('Alice:\n Net pay: {:.2f}'.format(alice.calculate_pay()))
barbara = Employee()
barbara.wage = 11.50
barbara.hours_worked = 20
print('Barbara:\n Net pay: {:.2f}'.format(barbara.calculate_pay()))
Works for me:
class C:
def f(a, b):
return a + b
x = f(1,2)
print(C.x)
but you should not do such things. Code in class-level is executing when class is "creating", usually you want static methods or class methods (decorated with #staticmethod or #classmethod) and execute code in some function/instantiated class. Also you can execute it on top (module) level if this is the simple script. Your snippet is "bad practice": class level (i'm talking about indentation) is for declarations, not for execution of something. On class-level is normal to execute code which is analogue of C macros: for example, to call decorator, to transform some method/attribute/etc - static things which are "pure" functions!

Categories

Resources