class City(Object):
symbol = "1"
name = "City"
priority = 30 # Should actually be above mob layer.
size = 5
starting_citizens = 5
citizens = []
resources = {"food" : 100,
"wood" : 0,
"iron" : 0}
inventory = []
needs_processing = True
action_time = 6
def __init__(self, loc, x, y):
global log
log = log + "A new town has been settled!\n"
self.name = self.name + " " + str(random.randrange(1, 999))
super().__init__(loc, x, y)
print(len(self.citizens))
print("Procedure undergoing in: " + self.name)
for N in range(self.starting_citizens - 1):
print("Another one bites the city")
self.add_citizen(Peasant)
print("CITY INIT END")
print(len(self.citizens))
print(self.citizens)
def add_citizen(self, citizen_type):
print("Procedure undergoing in: " + self.name)
print(str(len(self.citizens)) + " before adding occured")
self.citizens.append(citizen_type(self, -2, -2)) #Huehuehue. -2 -2 won't be qdeled.
print(str(len(self.citizens)) + " after adding occured")
For any amount of reasons, all class City objects share the citizens list. It is identical in each one, what is not something I would like. I would like to have each Class have it's own list.
No amount of debugging helped me see the problem.
http://prntscr.com/kgz5as
That is because you defined your citizens list to be a class variable instead of an instance variable. It is therefore being shared between all instances. (See 9.3.5 in the Docs page on classes)
You actually have multiple variables that should probably be instance variables instead of being shared by all isntances of the class (like citizens, size, name etc.). Define them as isntance variables instead like so:
def __init__(self, loc, x, y):
self.citizens = []
Related
I am using eval to run a generated string to append the newly created EggOrder instance to the list of the correct instance of the DailyOrders class. The day provided by EggOrder is used to used to append to the correct instance. This relies on eval and the variable name of the DailyOrders instance and so it would be great to get this removed. I know there must be a better way.
class DailyOrders:
PRICE_PER_DOZEN = 6.5
def __init__(self, day):
self.orders = []
self.day = day
def total_eggs(self):
total_eggs = 0
for order in self.orders:
total_eggs += order.eggs
return total_eggs
def show_report(self):
if self.total_eggs() < 0:
print("No Orders")
else:
print(f"Summary:\nTotal Eggs Ordered: {self.total_eggs()}")
print(f"Average Eggs Per Customer: {self.total_eggs() / len(self.orders):.0f}\n*********")
class EggOrder():
def __init__(self, eggs=0, name="", day=""):
if not name:
self.new_order()
else:
self.name = name
self.eggs = eggs
self.day = day
eval(f"{self.day.lower()}.orders.append(self)")
def new_order(self):
self.name = string_checker("Name: ")
self.eggs = num_checker("Number of Eggs: ")
self.day = string_checker("Date: ")
def get_dozens(self):
if self.eggs % 12 != 0:
dozens = int(math.ceil(self.eggs / 12))
else:
dozens = self.eggs / 12
return dozens
def show_order(self):
print(f"{self.name} ordered {self.eggs} eggs. The price is ${self.get_dozens() * DailyOrders.PRICE_PER_DOZEN}.")
if __name__ == "__main__":
friday = DailyOrders("Friday")
friday_order = EggOrder(12, "Someone", "Friday")
friday_order.show_order()
friday.show_report()
saturday = DailyOrders("Saturday")
saturday_order = EggOrder(19, "Something", "Saturday")
saturday_order = EggOrder(27, "Alex Stiles", "Saturday")
saturday.show_report()
DailyOrders isn't actually a superclass (it was in a earlier version), it acts like one and I suspect the answer might have some inheritance.
So, I'm tring to program a variant of the knapsack problem but I'm really new to the use of Python and I stumbled on this.
I'm using Jupyter (Python 3)
class Gene(object):
def __init__(self, weight, price):
self.weight = weight
self.price = price
obj1 = Gene(10, 20)
obj2 = Gene(25, 5)
obj3 = Gene(5, 10)
genes = [obj1, obj2, obj3]
class Chromosomes(object):
def __init__(self, flagIndex_of_items_contained = []):
self.flagIndex_of_items_contained = flagIndex_of_items_contained
self.myWeight = self.Define_myWeight()
def Define_myWeight(self):
weight = 0
for index_flag in range(len(self.flagIndex_of_items_contained)):
if(self.flagIndex_of_items_contained[index_flag] == 1):
weight = weight + genes[index_flag].weight
return weight
chromosome1 = Chromosomes([1,0,1])
print("chromosome1 weight: ", chromosome1.myWeight)
Output
chromosome1 weight: 15
BUT
genes[index_flag].weight
How can this command work if i don't pass the array genes to the class?
The problem is that your variable genes lives on the same level as the classes, the module level. In the problematic line
weight = weight + genes[index_flag].weight
the interpreter simply sees that there is no local variable with the scope of the function Define_myWeight, hence it checks the global scope (module level). On this level genes exists and the interpreter can use it.
Besides that, issues because of which your code has been considered "badly written".
Use global variables only if they are absolutely necessary. Check some arbitrary tutorial on globals to understand this proposition.
You should never use a mutable object as default parameter. Lists are mutable objects in Python, that means they can be changed. Use immutable objects, like tuples, in such cases.
def func1(some_arg = []): # bad
def func1(some_arg = ()): # ok
Do not mix different format styles. Use either CamelCase or names_with_underscores. Check out the Python Style Guide for that.
Here is an idea to improve your code. Chromosomes are made up of different genes. The following code models this relation.
class Gene:
def __init__(self, weight, price):
self.weight = weight
self.price = price
class Chromosom:
def __init__(self):
self.genes = []
self.flag_idx = []
self.weight = 0
def add_gene(self, weight, price):
self.genes.append(Gene(weight, price))
def compute_weight(self, flags):
for i, flag in enumerate(flags):
if flag == 1:
self.weight += self.genes[i].weight
Usage:
ch = Chromosom()
ch.add_gene(10, 20)
ch.add_gene(25, 5)
ch.add_gene(5, 10)
ch.compute_weight((1, 0, 1))
print(ch.weight)
Consider the following Python code snippet where we define a Portfolio, Company and Deposit class. A Portfolio object simply acts as a union of companies & deposits. And we can run metrics on the portfolio like Profit. Questions:
For every new metric I include in the Company or Deposit class I need to manually add a corresponding function in the Portfolio class; despite the fact that their behaviour is always the same: sum across all investments. Is there a way to improve this logic/construction of classes? What if we need to add 100 other metrics...
The Deposit class only has a Profit function, but not Loss (interest in a bank account is assumed to be guaranteed). Is there a way to treat "undefined" metrics as always returning 0? Or is there a cleaner/more correct to define these metrics? What if we need to cover 100 different investment types that may or may not have different metrics...
class Company():
def __init__(self, ItemsSold, ItemPrice, Expenses, Fines):
self.ItemsSold = ItemsSold
self.ItemPrice = ItemPrice
self.Expenses = Expenses
self.Fines = Fines
def Profit(self):
return self.ItemsSold * self.ItemPrice
def Loss(self):
return self.Expenses + self.Fines
def ProfitAndLoss(self):
return self.Profit() - self.Loss()
class Portfolio():
def __init__(self, Investments):
self.Investments = Investments
def Profit(self):
return sum([inv.Profit() for inv in self.Investments])
def Loss(self):
return sum([inv.Loss() for inv in self.Investments])
def ProfitAndLoss(self):
return sum([inv.ProfitAndLoss() for inv in self.Investments])
class Deposit():
def __init__(self, Notional, InterestRate, TimeHorizon):
self.Notional = Notional
self.InterestRate = InterestRate
self.TimeHorizon = TimeHorizon
def Profit(self):
return self.Notional * self.InterestRate * self.TimeHorizon
myComp1 = Company(100,2,50,20)
myComp2 = Company(200,2,100,80)
myDepos = Deposit(100,0.02,3)
myPortf = Portfolio([myComp1,myComp2,myDepos])
print(myPortf.Profit()) # Works fine
print(myPortf.ProfitAndLoss()) # Throws an error
The second question is easy: all you have to do is to create a Base class where each metrics is defined as a method returning 0. Then derive all your Invest classes (Company, Deposit, etc) from the Base class, so as all undefined metrics will call the corresponding method in the Base class.
The first question is a bit tougher as it requires some meta-programming. Your Portfolio class can also be derived from the Base class, then it looks in the method dictionary of the Base class (Base.__dict__) to retrieve all metrics names. Afterwards, for all these metrics, it creates a specific lambda method that calls this metrics for each item in your Investments list and sums up the results. Here is a skeleton code for this:
class Base(object):
def f1(self):
return 0
def f2(self):
return 0
class InvestA(Base):
def f2(self):
return 2
class InvestB(Base):
def f1(self):
return 1
class Portfolio(Base):
def __init__(self, invest):
self.invest = invest
for name in [n for n in Base.__dict__ if n[:2] != '__']:
self.__dict__[name] = lambda name=name: self.sum(name)
def sum(self, name):
return sum([i.__class__.__dict__[name](i) for i in self.invest
if name in i.__class__.__dict__])
A = InvestA()
print("A.f1 = %s, A.f2 = %s" % (A.f1(), A.f2()))
B = InvestB()
print("B.f1 = %s, B.f2 = %s" % (B.f1(), B.f2()))
P = Portfolio([A,A,B])
print('P.f1 = A.f1 + A.f1 + B.f1 =', P.f1())
print('P.f2 = A.f2 + A.f2 + B.f2 =', P.f2())
which produces the following output:
A.f1 = 0, A.f2 = 2
B.f1 = 1, B.f2 = 0
P.f1 = A.f1 + A.f1 + B.f1 = 1
P.f2 = A.f2 + A.f2 + B.f2 = 4
As you can see, A.f1, B.f2, P.f1 and P.f2 are not explicitely defined as methods, but they can be called thanks to inheritance and meta-programming
Me very very new programmer, I'm new to classes and not sure how to set up a print method for this class. How do I go about setting up a print method for my class here? Thanks for anything!
class travelItem :
def __init__(self, itemID, itemName, itemCount) :
self.id = itemID
self.name = itemName
self.itemCount = itemCount
self.transactions = []
def getID(self) :
return(self, id)
def getName(self) :
return(self.name)
def setName(self, newName) :
self.name = newName
def getAvailableStart(self):
return(self.AvailableStart)
def appendTransaction(self, num) :
self.transactions.append(num)
def getTransactions(self) :
return(self.transactions)
def getReservations(self) :
Additions = 0
for num in self.transactions :
if (num > 0) :
Additions = Additions + num
return(Additions)
def getCancellations(self) :
Subtractions = 0
for num in self.transactions :
if (num < 0) :
Subtractions = Subtractions + num
return(Subtractions)
def getAvailableEnd(self) :
total = self.AvailableStart
for num in self.transactions :
total = total + num
return(total)
Remember that a method is called on an instance of a class, so if you mean to create a true method that just prints a class you can write something like
class Foo(object):
def print_me(self):
print(self)
foo_instance= Foo()
foo_instance.print_me()
But it sounds like you want to customize the output of print(). That is what the built in method __str__ is for, so try this.
class Foo(object):
def __str__(self):
# remember to coerce everything returned to a string please!
return str(self.some_attribute_of_this_foo_instance)
a good example from your code might be
...
def __str__(self):
return self.getName + ' with id number: ' + str(self.getId) + 'has ' + str(self.getTransactions) + ' transactions'
You must use a __str__ special method:
class travelItem:
...
def __str__(self):
return "a string that describe the data I want printed when print(instance of class) is called"
So I was writing a program in Python, which would take all my university classes (from csv) and print info about them. I've wrote a simple class Subject to manage everything better. In my uni there are classes in even weeks, odd weeks, and every-week classes, and I have lectures, exercises and laboratories. So my Subject class is like this:
class Subject:
number = 0
name = ""
dummyData = []
even = {}
odd = {}
all = {}
type = ""
def __init__(self, name, number, type):
self.name = name
self.number = number
self.type = type
self.info = str(number) + " " + name + " " + type
Previously I had all days written in even, odd, and all dicts, like this:
even = {"mon":"",
"tue":"",
"wed":"",
"thu":"",
"fri":"",
}
So I could add all the classes hours to specific day key. But, there was a problem. For example lets say Programming lecture is subject 1 and Programming laboratories are subject 2. Subject 1 is on Monday at 9.15. Subject 2 is on Monday as well, but at 17.05. So I have a function, which would check if the subject is on even/odd week or it is every week. And then I would assign f.e 9.15 to even["mon"] on subject 1. Then I would go for subject 2, and tried to add 17.05 to even["mon"]. Every subject was an other Subject class object stored in a list. But there was a mistake. When I tried to add 17.05 to subject 2s even["mon"] it added it, okay, but then even["mon"] should ="17.05", but it was ="9.15/17.05". I was trying to figure out whats wrong, and I finally did, by changing my class from:
class Subject:
number = 0
name = ""
dummyData = []
even = {"mon":"",
"tue":"",
"wed":"",
"thu":"",
"fri":"",
}
...etc...
type = ""
def __init__(self, name, number, type):
self.name = name
self.number = number
self.type = type
self.info = str(number) + " " + name + " " + type
to:
class Subject:
number = 0
name = ""
dummyData = []
even = {}
odd = {}
all = {}
type = ""
def __init__(self, name, number, type):
self.name = name
self.number = number
self.type = type
self.info = str(number) + " " + name + " " + type
self.even = {"mon":"",
"tue":"",
"wed":"",
"thu":"",
"fri":"",
}
+ odd and all. So why is Python like remembering whats been written into the first object attributes?
You need to declare the attributes inside the __init__ method. Here's an example
class Subject:
def __init__(self, name, number, type):
self.number = number
self.name = name
self.dummyData = []
self.even = {}
self.odd = {}
self.all = {}
self.type = type
Declaring the variables inside the class declaration makes them "class" members and not instance members. Declaring them in the __init__ method makes ensures a new instance of the members is created every time you create a new instance of the object.