making a class instance to separate and organize classes - python-3.x

I am wanting to make a Python program to help in choosing a Nerf war load out by allowing me to enter data that I get, such as how far the gun shoots, it's size, weight, type, ect. then I want to create different functions that will allow me to pull up optimal builds such as a sniper build for example.
I made a class so I can enter all the information for each gun into it's own class.
I am not sure how to approach making a function for example "sniper" that will pull only sniper types then put them in order by how far their shooting distance is.
I am thinking about a for loop but I am not sure how to approach it.
class Nerf_Gun:
def __init__(self, name, size, weight, DPS, distance, slots, type):
self.name = name
self.size = size
self.weight = weight
self.DPS = DPS
self.distance = distance
self.slots = slots
self.type = type
def sniper(self):
if Nerf_Gun.type() == "Sniper":

You want to create different types of guns which may belong to broad categories, hence you are looking for the concept of inheritance. Look up https://www.w3schools.com/python/python_inheritance.asp. In general, if you are looking to make those attributes configurable for each "instance" of a gun, I would make it through attrs.
#attr.s
class Gun:
name: str = attr.ib()
size: int = attr.ib()
weight: int = attr.ib()
DPS: str = attr.ib()
distance: str = attr.ib()
slots: str = attr.ib()
type: str = attr.ib()
Sniper = attr.make_class('Sniper', {}, bases=(Gun,))
#initialize instance
nerf_gun = Sniper(name='sniper', size=2, weight=3, DPS='123', distance='123', slots='456', type='789')
You can play around with making these attributes optional or override them in Sniper class etc.
However, if you want to keep them constant across the class (all snipers have the same values for each gun), I would initialize the class with variables, exactly like you were, but make subclasses for Sniper etc like so:
class Sniper(Nerf_Gun):
def __init__(self):
self.name = 'Sniper'
self.weight = 123
# fix the rest of attrs

Related

Accessing variables from a method in class A and using it in Class B in python3.5

I have a BaseClass and two classes (Volume and testing) which inherits from the BaseClass. The class "Volume" use a method "driving_style" from another python module. I am trying to write another method "test_Score" which wants to access variables computed in the method "driving_style" which I want to use to compute further. These results will be accessed to the class "testing" as shown.
from training import Accuracy
import ComputeData
import model
class BaseClass(object):
def __init__(self, connections):
self.Type = 'Stock'
self.A = connections.A
self.log = self.B.log
def getIDs(self, assets):
ids = pandas.Series(assets.ids, index=assets.B)
return ids
class Volume(BaseClass):
def __init__(self, connections):
BaseClass.__init__(self, connections)
self.daystrade = 30
self.high_low = True
def learning(self, data, rootClass):
params.daystrade = self.daystrade
params.high_low = self.high_low
style = Accuracy.driving_style()
return self.Object(data.universe, style)
class testing(BaseClass):
def __init__(self, connections):
BaseClass.__init__(self, connections)
def learning(self, data, rootClass):
test_score = Accuracy.test_score()
return self.Object(data.universe, test_score)
def driving_style(date, modelDays, params):
daystrade = params.daystrade
high_low = params.high_low
DriveDays = model.DateRange(date, params.daystrade)
StopBy = ComputeData.instability(DriveDays)
if high_low:
style = ma.average(StopBy)
else:
style = ma.mean(StopBy)
return style
def test_score(date, modelDays, params):
"want to access the following from the method driving_style:"
DriveDays =
StopBy =
return test_score ("which i compute using values DriveDays and StopBy and use test_score in the method learning inside
the 'class - testing' which inherits some params from the BaseClass")
You can't use locals from a call to a function that was made elsewhere and has already returned.
A bad solution is to store them as globals that you can read from later (but that get replaced on every new call). A better solution might to return the relevant info to the caller along with the existing return values (return style, DriveDays, StopBy) and somehow get it to where it needs to go. If necessary, you could wrap the function into a class and store the computed values as attributes on an instance of the class, while keeping the return type the same.
But the best solution is probably to refactor, so the stuff you want is computed by dedicated methods that you can call directly from test_score and driving_style independently, without duplicating code or creating complicated state dependencies.
In short, basically any time you think you need to access locals from another function, you're almost certainly experiencing an XY problem.

Can anyone explain me about __init_ in Python?

List item
class Car:
def __init__(self, color, brand, number_of_seats):
self.color = color
self.brand = brand
self.number_of_seats = number_of_seats
self.number_of_wheels = 4
self.registration_number = GenerateRegistrationNumber()
Hi all,
1)Referring to the above example, could anyone tell me what is the difference between specific attributed and "the other" attributes? What will happen if registration_number is treated as a specific attribute?
2)
class MyInteger:
def __init__(self, newvalue):
# imagine self as an index card.
# under the heading of "value", we will write
# the contents of the variable newvalue.
self.value = newvalue
If we consider this example, shouldn't it be self.newvalue = newvalue?
I think I know what you're asking (let me know if I'm wrong), but I think you're asking what the difference is between the attributes that are assigned by the parameters of __init__ (Instance Attributes), ones that are assigned inside the __init__ method but not with parameters (also Instance Attributes), and ones that are not assigned in the initialiser at all (Class Attributes). The difference here is that all (well, pretty much all) cars have 4 wheels, and the number plate is generated, not supplied. You could also do this, for example:
class Car:
number_of_wheels = 4
def __init__(self, color, brand, number_of_seats):
self.color = color
self.brand = brand
self.number_of_seats = number_of_seats
self.registration_number = GenerateRegistrationNumber()
As the number of wheels here is always assigned to the same value, across all instances, it is said to be a "Class Attribute" in this case. All other attributes here are “Instance Attributes” as they are specifically assigned to each instance. For a slightly better explanation, I recommend reading this:
https://www.geeksforgeeks.org/class-instance-attributes-python/
It doesn't actually matter what the instance attribute (self.value here) is called, you could call it whatever you want and it'd still work, but in most cases, you would indeed want to name the attribute the same as the parameter.
init function also called as magic function is a constructor function for a class. if you remember in java whenever we make a class the constructor method should have the same name as the classname but this is not the scenario in python . In python we make use of the init method
the difference between the class attributes and instance attributes is that the class attributes are common to every object that is created but the instance attributes are only accessible by the object that is created.
consider a example where data of students in a class is stored. In such case the class division will be same for all the students of that particular class so it can be common but names of all students are different and also their marks and so on and hence they should be different for everyone
in previous scenario the class division can be class attribute and the data of student like name , marks has to be instance attributes
examples of class attribute is as shown
class A:
Division = 5A
here the division is a class attribute
class B:
def __init__(self,name,marks):
self.name = name
self.marks = marks
here the name and marks are instance variables
now here we can also write self.username = name because we are storing the value of name variable in self.username so you can write any name there is no constraint on that
Also whenever you write __ in front of method or variable it means that the attribute is private and accessible by only class.

Perform operations on values with class attributes

Let's say I've made a simple class
class mercury:
class orbial_characteristics:
apehilion = 69816900
perihilion = 46001200
semi_major_axis = 57909050
eccentricity = 0.205630
orbital_period = 87.9691*86400
orbital_speed = 47.362*1e3
Now, the values given here are in SI units, the value of apehilion for example, is in km. I want to make another class that can convert the value to a given unit, let's say astronomical unit. One method is to pass the value of apehilion directly to that class
change_to_AU(value_of_apehilion)
Which is relatively easy to do. However, what I'm looking for is in the lines of python core operations. Something like this
merc_apehilion_km = mercury.orbital_characteristics.apehilion
merc_apehilion_au = merc_apehilion_km.change_to_AU()
I have recently started working on classes, by reading answers here and web tutorials but I do not get how such an operation can be performed. I even try reading the core files from numpy and pandas as these two libraries that I use most have a number of things that use this notation.
Edit:
A little research led me to this stack overflow page. Take a look at the libraries mentioned in it, make sure they are actively maintained, and consider using them over doing what I demonstrate below
End of Edit
Creating custom methods like this would involve you creating a custom Object for your SI unit values. Here is an example:
class SIUnit:
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
def to_astronimical_units(self):
Calculations which convert apehilion to AU go here
return result
class mercury:
class orbial_characteristics:
apehilion = SIUnit(69816900)
perihilion = SIUnit(46001200)
semi_major_axis = SIUnit(57909050)
eccentricity = SIUnit(0.205630)
orbital_period = SIUnit(87.9691*86400)
orbital_speed = SIUnit(47.362*1e3)
Keep in mind that the to_astronomical_units method would exist for all SI units you use, not just distance so you may want to create a base SIUnit class then have a subclass for each SI Unit, e.g:
class SIUnit:
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
class Kilometer(SIUnit):
def to_au(self):
Calculations which convert apehilion to AU go here
return result
class Ampere(SIUnit):
def to_volts(self, wattage):
return self.value / wattage

How to better structure my classes and properties?

I am trying to programme a board game using python and object orientated programming. However, the structure of my classes and properties seems a bit tortuous even if I have made it do what I want. It doesn't seem very elegant and I'm sure it will lead to things getting too complicated and making the code hard to follow as I progress. I will try to give a simplified example of how I've structured things:
class GameState:
def __init__(self, n_players):
self.n_players = n_players
self.players = []
for player in range(self.n_players):
self.players.append(Player(player))
// other properties
// other functions
class Player:
def __init__(self, name):
self.name = name
self.building = Building()
self.workers = 3
// other properties
class Building:
def __init__(self):
self.worker = False
def action(self, player):
if self.worker == True:
player.workers += 1
But now if I want a player to use the building action I have to do something like the below. It feels like I should be able to structure things better to avoid having to pass an instance of a Player class to the Building action function.
game = GameState(4)
game.players[0].building.action(game.players[0])
The idea is that each player will have an instance of the Building class.
It's hard to suggest alternatives without knowing the exact format of your game. If each building is only ever associated with a single player at a time, I'd add that to the initialisation and reference it directly.
class Building:
def __init__(self, player):
self.worker = False
self.player = player
def action(self):
if self.worker == True:
self.player.workers += 1
Alternatively, if each player will only ever have one building associated with them, then the action function should probably be in the player class rather than the building.

Another Name error for my text adventure game Python

So i am making a text adventure game, and currently i am making the enemies. My class random_enemies makes trash mobs for your character to fight and i have a function in it called weak, normal, strong, etc... that scales with your character depending on which one it is. When i call random_enemies.weak it says (Name Error: global variable "p" is not defined) even though it should be.
import random
from character import *
from player import *
class random_enemies(character):
def __init__(self,name,hp,maxhp,attack_damage,ability_power,exp):
super(random_enemies,self).__init__(name,hp,maxhp)
self.attack_damage = attack_damage
self.ability_power = ability_power
self.exp = exp
def weak():
self.hp = random.randint(p.maxhp/10, p.maxhp/5)
self.attack_damage = None
self.ability_power = None
self.exp = None
from character import*
class player(character):
def __init__(self,name,hp,maxhp,attack_damage,ability_power):
super(player,self).__init__(name, hp, maxhp)
self.attack_damage = attack_damage
self.ability_power = ability_power
This is my player class and below is the class that player gets "maxhp" from.
class character(object):
def __init__(self,name,hp,maxhp):
self.name = name
self.hp = hp
self.maxhp = maxhp
def attack(self,other):
pass
p=player(Players_name, 100, 100, 10, 5,)
while (p.hp>0):
a=input("What do you want to do?")
if a=="Instructions":
Instructions()
elif a=="Commands":
Commands()
elif a=="Fight":
print("Level",wave,"Wave Begins")
if wave < 6:
b = random_enemies.weak()
print("A",b,"Appeared!")
print("Stats of",b, ": \n Health=", b.hp,"Attack Damage=",b.attack_damage)
continue
I just made this really quickly just to test if everything I had was working until I got the error. This is also the place where random_enemies.weak() was called. Also in this is where I defined what "p" was.
So, first of all, follow a naming convention. For python code I recommend that you use pep8 as a convention.
You have a problem with classes vs. instances in your code. First, you need an instance of a class before you can use it:
enemy = random_enemy() # a better name would be RandomEnemy
In Python, all methods start with self, and you need to pass to the method the arguments that it needs to do its work. weak is a method, so it should be more like this:
def weak(self, player):
# the method for weak ... weak attack ?
# remember to change p to player, which is more meaningful
...
Now that you have your instance and it has a method weak which receives a player as argument, you can use it as follows:
# you can't use random_enemy here as you tried because it is a class
# you need a random_enemy instance, the enemy that I talked about earlier
b = enemy.weak(player) # renamed p to player because it is more meaningful
For this all to work, you will need one more thing. weak() needs to return something. Right now you are using what it returns, nothing! The code that you posted is b = random_enemies.weak(). Because weak() does not have a return clause, b will always be None.
Some notes: Avoid one-letter variables unless there is a long standing convention (like using i for loop counter). It is easier to understand what you are trying to do if you define player instead of just p.
Python has a really great tutorial for all this stuff.

Resources