python - setting instance variable within the instance - python

I have the following tile class which got some instance variables such as UNMAPPED,FREE etc.
Those instance variables get a default value once new instance is created, but i want to set some of this variables from a method within the instance itself.
when im trying to do so, it seems the the new value is not saved but when im doing it without any method it seems to work.
How can it be?
class tile():
def __init__(self):
self.FREE = 0
self.UNMAPPED = 1
def set_tile(self,newVal):
self.FREE = newVal
so that :
tile1 = tile()
tile1.set_tile(20) -> tile1.FREE = 0
but,
tile1.FREE = 20 -> tile1.FREE = 20
thanks for your help

Related

Python - Problem returning True/False to class properties from class method

I have a class as below which within the __init__ method I am trying to assign a True/False value to a class property using a class method.
class Sensor:
def __init__(self, json_data):
self.sensor_eui = json_data['end_device_ids']['dev_eui']
self.reading1 = json_data['uplink_message']['decoded_payload']['temperature']
self.reading2 = json_data['uplink_message']['decoded_payload']['humidity']
self.tolerance_exceeded = self.tolerance_check
def tolerance_check(self):
sql = f"SELECT DefaultLowerLimit, DefaultUpperLimit FROM [dbo].[IoT_Sensors] WHERE
DeviceID = '{self.sensor_eui}'"
results = exec_sql(sql)
if (self.reading1 > int(results[0])) and (self.reading1 < int(results[1])):
return False
return True
The issue is, when trying to troubleshoot this and logging the objects to the console, instead of returning True or False as the assigned value of 'tolerance_exceeded' it returns the method and object:
logging.info(f'Tolerance Exceeded: {sensor.tolerance_exceeded}')
logs in the console as below:
[2022-10-26T12:08:08.025Z] Tolerance Exceeded: <bound method Sensor.tolerance_check of <__app__.IoT_Data-Handler.classes.Sensor object at 0x000001C834D45BE0>>
So what is going on here? I have not been coding long, but when I have done something similar in the past (assigning a string value from an API), it worked fine. This is for an Azure Function, but I cannot see how that would impact what I am trying to achieve.
Any help would be appreciated.
The issue in your code is that instead of calling the function you assign it. In order to call the function you have to add the parenthesis.
class Sensor:
def __init__(self, json_data):
self.sensor_eui = json_data['end_device_ids']['dev_eui']
self.reading1 = json_data['uplink_message']['decoded_payload']['temperature']
self.reading2 = json_data['uplink_message']['decoded_payload']['humidity']
# Calling tolerance_check and assigning return value to tolerance_exceeded
self.tolerance_exceeded = self.tolerance_check()

Dynamic O.O.P and instances

EDIT
I m trying to make a function to dynamic change the object to get acess to those classes easier.
How can i pass the "test" variable inside that object?
I'v tryied this so far.
EDIT
class Vision:
def find():
pass
class visionInstances:
visionPao = Vision(f'{PathMissionProducts}Pao.jpg')
visionLeite = Vision(f'{PathMissionProducts}Leite.jpg')
xabuska = visionInstances() #Classe
def catch_screenshot(wincap):
return wincap.get_screenshot()
def getpoints(VisionInstanceName=None, threshold=0.7):
test = VisionInstanceName
points = xabuska.visionPao.find(catch_screenshot(xabuska.wincap),threshold,"points")
points2 = xabuska.test.find(catch_screenshot(xabuska.wincap),threshold,"points")
return points2
This code returns "None"
Note on the code that "xabuska.visionPao.find" are 3 diferent objects.
I want to make the second object "test" dynamic.
points1 = is the value i want.
points2 = is the test, and return None

Editing Instance Attributes in Python

I have a python class called Player that looks like this ...
class Player:
def __init__(self):
self.display = 'A'
self.num_water_buckets = 0
self.row = 0
self.col = 0
I am having trouble editing the self.row and self.col ... maybe they're immutable but I haven't found much of this on the internet. Player().row and Player().col work, however they print 0 every time. I am trying to edit them using Player().row = value where value is a variable containing a number.
Thanks in advance!
UPDATE: Okay so I understand that you have to define a new occurrence of this instance using x = Player() then x.row = ...
But I need to originally initialise the variable with certain values (which are different every time) so I thought I could use a function and the return value from that function would set the initial value from the variable but it just creates an infinite recursion.
I did...
class Player:
def __init__(self):
from game_parser import read_lines
self.display = 'A'
self.num_water_buckets = 0
self.row = Player().detRow(sys.argv[1])
self.col = Player().detCol(sys.argv[1])
def detRow(fileName):
# use this function to return the row
def detCol(fileName):
# use this function to return the col
If you do
Player().row = value
print(Player().row)
The Player() in the first row creates a new instance; then you modify it by setting its row attribute to value; then you throw away that instance, because you haven't bothered to remember it anywhere. Then in the next row, you create a new instance (where the initialiser sets the row attribute to zero).
Not all players are interchangeable. If you sit John in the second row, it does not mean Harry will be in the second row too; it just means John is in the second row.
To do it correctly, store your Player instance in a variable:
john = Player()
john.row = 2
print(john.row)
You need to add put the variable outside the __init__() method
EDIT: added row and col to the class
class Player:
row = 0 # NO self here
col = 0
def __init__(self):
self.display = 'A'
self.num_water_buckets = 0
john = Player()
john.num_water_buckets = 12
print(f'before change: {john.col}')
john.col = 5
print(f'after change: {john.col}')
print(f'class property: {Player.col}') # note it did not change the class
Output:
before change: 0
after change: 5
class property: 0

How class level attribute values are evaluated in python? [duplicate]

This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 3 years ago.
I've the following class structure:
class StarCount:
one_stars = 0
two_stars = 0
three_stars = 0
four_stars = 0
five_stars = 0
class OrientationAnalysis:
straight = StarCount()
bisexual = StarCount()
gay = StarCount()
class GenderAnalysis:
men = OrientationAnalysis()
women = OrientationAnalysis()
I've written the following code:
genderanalysis = GenderAnalysis()
genderanalysis.men.straight.five_stars = 100
print genderanalysis.men.straight.five_stars # outputs 100
print genderanalysis.women.straight.five_stars # this is also 100
Why genderanalysis.women.straight.five_stars is also updated? I've checked the genderanalysis.women.gay.five_stars also but it's not updated?
When you declare some variables like this:
class StarCount:
one_stars = 0
two_stars = 0
three_stars = 0
four_stars = 0
five_stars = 0
These variables become class variables. Class variables are variables that are shared by all instances of a class. So when you updated genderanalysis.men.straight.five_stars, it actually updated StarCount.five_stars and as genderanalysis.women.straight.five_stars also points to the same variable, it seemed to have updated too.
I think what you are looking for are instance variables. You can declare them like this:
class StarCount:
def __init__(self):
self.one_stars = 0
self.two_stars = 0
self.three_stars = 0
self.four_stars = 0
self.five_stars = 0
Edit
Why genderanalysis.women.gay.five_stars is not updated?
What happens is that before you updated any variable of genderanalysis object, all of the variables were pointing to the variables of StarCount class. As you can see they have same id:
print(id(StarCount.five_stars)) # prints '94016229389744'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229389744'
print(id(genderanalysis.women.gay.five_stars)) # prints '94016229389744'
But when you changed genderanalysis.men.straight.five_stars, the reference/pointer got replaced with your provided value, in this case 100. You can see difference in their id's:
print(id(StarCount.five_stars)) # prints '94016229389744'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229391328', see the difference?
So now genderanalysis.men.straight.five_stars does not point to StarCount.five_stars, rather it points to OrientationAnalysis.straight.five_stars. Once again, let's check their id's:
print(id(OrientationAnalysis.straight.five_stars)) # prints '94016229391328'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229391328', same right?
Now onto your question, at this point genderanalysis.women.gay.five_stars is still untouched so it points to StarCount.five_stars and so it still prints 0. Change StarCount.five_stars and you can see the change reflecting in genderanalysis.women.gay.five_stars.
StarCount.five_stars = 101
print(genderanalysis.women.gay.five_stars) # prints `101`
Define the values in the init methods of the classes, so that they become attached to intance objects, not the class object itself.
class StarCount:
def __init__(self):
self.one_stars = 0
self.two_stars = 0
self.three_stars = 0
self.four_stars = 0
self.five_stars = 0
class OrientationAnalysis:
def __init__(self):
self.straight = StarCount()
self.bisexual = StarCount()
self.gay = StarCount()
class GenderAnalysis:
def __init__(self):
self.men = OrientationAnalysis()
self.women = OrientationAnalysis()
genderanalysis = GenderAnalysis()
genderanalysis.men.straight.five_stars = 100
print genderanalysis.men.straight.five_stars # outputs 100
print genderanalysis.women.straight.five_stars # this is now 0
your attributes should not be class attributes but instance attributes instead. this would be a start for you:
class StarCount:
def __init__(self, five_stars=0):
self.five_stars = five_stars
# ...
class OrientationAnalysis:
def __init__(self):
self.straight = StarCount()
# ...
class GenderAnalysis:
def __init__(self):
self.men = OrientationAnalysis()
self.women = OrientationAnalysis()
you’re almost there— you are referencing and modifying class variables rather than instance variables.
You need an __init__(self) method, and to create all the attributes on self

Trying to build trie with classes in python - strange behavior

I'm trying to implement trie in python. I'm using dictionaries+classes instead of lists (I know it's not optimal, but I'm just trying to make it work at all).
After debugging I found out that each layer has all letters in dictionary. I cannot understand why.
Here is my code (implementation is 100% most basic, straightforward):
class lttr:
finish = 0
pointers = {} #for letters to reference class instance
eps = lttr()
def add(word):
global eps
last = eps
for ind,x in enumerate(word):
if last.pointers.get(x,None):
last = last.pointers[x]
else:
last.pointers[x] = lttr()
last=last.pointers[x]
last.finish=1
def lookup(word):
global eps
last=eps
for ind,x in enumerate(word):
if last.pointers.get(x,None):
last=last.pointers[x]
else:
return False
return bool(last.finish)
add("pear")
print lookup("ar") #prints True ... but why?
I'm guessing you intended for each individual lttr instance to have its own unique values for finish and pointers. In which case, you need to declare them as attributes of self inside __init__, rather than just defining them at the class scope.
class lttr:
def __init__(self):
self.finish = 0
self.pointers = {} #for letters to reference class instance
Now your script will print False as expected.
Your lttr class has class variables, but you want instance variables. Class variables are unique across all instances of that class, so you only have one pointers object.
class lttr:
finish = 0
pointers = {} #for letters to reference class instance
What you want is
class lttr:
def __init__(self):
self.finish = 0
self.pointers = {}
and that works as expected.

Categories