Working with classes - resolve a NameError: global name - python

I am working with class object in order to improve my skills in programming.
I have three files *.py. Sorry for the basic example but help me to understand where my error is:
/my_work_directory
/core.py *# Contains the code to actually do calculations.*
/main.py *# Starts the application*
/Myclass.py *# Contains the code of class*
in Myclass.py
class Point(object):
__slots__= ("x","y","z","data","_intensity",\
"_return_number","_classification")
def __init__(self,x,y,z):
self.x = float(x)
self.y = float(y)
self.z = float(z)
self.data = [self.x,self.y,self.z]
def point_below_threshold(self,threshold):
"""Check if the z value of a Point is below (True, False otherwise) a
low Threshold"""
return check_below_threshold(self.z,threshold)
in core.py
def check_below_threshold(value,threshold):
below = False
if value - threshold < 0:
below = not below
return below
def check_above_threshold(value,threshold):
above = False
if value - threshold > 0:
above = not above
return above
when I set main.py
import os
os.chdir("~~my_work_directory~~") # where `core.py` and `Myclass.py` are located
from core import *
from Myclass import *
mypoint = Point(1,2,3)
mypoint.point_below_threshold(5)
I get:
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "Myclass.py", line 75, in point_below_threshold
return check_below_threshold(self.z,threshold)
NameError: global name 'check_below_threshold' is not defined

Functions in other modules are not automatically visible in your Myclass module. You need to explicitly import them:
from core import check_below_threshold
or import the core module and use that as a namespace:
import core
# ...
return core.check_below_threshold(self.z,threshold)

You have a missing import.
You have to import your functions where you use them.
That means, you have to import check_below_threshhold in the core.py too, because it gets used there.

Related

Importing a python module

I built a small demo script, which I want to import into another python script. The code is as follows:
class count:
def __init__(self):
def students(self,males,females):
return males + females
def teachers(self,bsc,nce):
return bsc - nce
def cleaners(self,older,younger):
return older + younger
class salary(count):
def __init__(self):
count.__init__(self)
def teachers_salary(self,teachers,amount):
return teachers * amount
def cleaner_salary(self,cleaners,amount):
return cleaners * amount
def gardeners_salary(self,gardeners,amount):
return gardeners * amount
I saved this script as count.py and I now want to import it into another script, so that I can use its modules. But when I use from count import salary and then run the code salary.teachers(bsc=10,nce=15), I get the error message below:
TypeError Traceback (most recent call last)
<ipython-input-62-b9aec73e51ba> in <module>
----> 1 print(salary.teachers(bsc=10,nce=15))
TypeError: teachers() missing 1 required positional argument: 'self'
Please, can someone advise me on what I am not doing right? Thanks as always.

Python Troubles (Missing 1 required positional argument: 'self')

i'm trying to solve the adventofcode riddles, but this year i decided to take the chance to learn a new programming language: Python.
Since i already have some knowledge about other OOP languages like Java and C++, i immediately created an "interface" system for the Solutions objects.
My project setup at the moment is like:
Project Setup
Now what i want is to dynamically output solutions through the main class, that basically has to call all .solve() method of each dayX.py class that is in the /solutions/ directory.
I think i'm next to do it but i get an error:
Traceback (most recent call last):
File "C:\Users\siste\j-workspace\adventofcode2020\main.py", line 16, in <module>
print(solution.solve())
TypeError: solve() missing 1 required positional argument: 'self'
Here are my files:
main.py
import os
def days():
classes = []
path = "C:\\path"
for file in os.listdir(path):
if(file.startswith("day")) :
classes.append(str(file.replace(".py", "")))
return classes
if __name__ == '__main__':
for day in days() :
solution = getattr(__import__(str("solutions." + day)), day.replace("d", "D"))
print(solution.solve())
solution.py
path = "C:\\path\\inputs\\day{}.txt"
class Solution:
def __init__(self, dayNumber):
self.dayNumber = dayNumber
self.inputPath = path.format(self.dayNumber)
def part1(self):
pass
def part2(self):
pass
def solve(self):
return ("Day {} Solutions: \n\tPart1: {}\n\tPart2: {}"
.format(self.dayNumber, self.part1(), self.part2()))
day1.py
import fileinput
from solutions.solution import Solution
class Day1(Solution):
def __init__(self):
super().__init__(1)
def part1(self):
return "sol"
def part2(self):
return "sol2"
When you're using the getattr on the imported module, you're getting the class definition. Methods are only callable on class instances, otherwise they throw the error you're seeing:
class A:
def a(self):
pass
A.a() // Will throw "TypeError: a() missing 1 required positional argument: 'self'"
A().a() // OK
Changing the __main__ part this way should solve the issue:
if __name__ == '__main__':
for day in days() :
day_class = getattr(__import__(str("solutions." + day)), day.replace("d", "D"))
day_instance = day_class()
print(day_instance.solve())

Mocking local function from another file

I need to patch a function imported from the same file containing another function I want to test, but it's not working =/.
# funcs.py
def func_one():
return 1
def func_two():
return func_one() + 2
from .funcs import func_two
class TestFunc(TestCase):
def test_func_two(self):
with patch('func_one', 0):
result = func_two()
The result should be two but I got an error with the test:
TypeError: Need a valid target to patch. You supplied: 'func_one'
I need to import the absolute path of the function:
from .funcs import func_two
class TestFunc(TestCase):
def test_func_two(self):
#patch('funcs.func_one', MagicMock(return_value=0)):
result = func_two()
Where funcs.func_one is the entire module path + func name.

python oop import - NameError confusion

I wrote some code that was meant to try to approach a target string by selecting randomly from a list of chars, but I have some problem that I do not quite understand.
import random
class MonkiesGo:
__chars = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
def __init__(self, targetString):
__targetString = targetString.lower()
__targetList = list(targetString)
__attemptList = []
__unmatchedIndexes = [ x for x in range(0, (len(targetString)-1)) ]
def attemptToSolve(self):
if len(__unmatchedIndexes) == 0:
__attemptString = ''.join(__attemptList)
return __attemptString, __targetString
else:
for index in __unmatchedIndexes:
__attemptList[index] = randomChar()
def updateSolutionProgress(self):
for indexCheck in __unmatchedIndexes:
if __targetList[index] == __attemptList[index]:
__indexToClear = __unmatchedIndexes.index(index)
del __unmatchedIndexes[indextToClear]
def __randomChar(self):
return __chars[ random.randint(0,26) ]
when I import it into a python shell in my terminal, make an object as follows:
from monkies import MonkiesGo
mk = MonkiesGo("hello")
mk.attemptToSolve()
I get the error:
Traceback (most recent call last):
File "", line 1, in
File "path/to/the/file/monkies.py", line 15, in attemptToSolve
if len(__unmatched 0: NameError: name '_MonkiesGo__unmatched' is not defined
What is causing this, and why is there an underscore before MonkiesGo?
THanks in advance.
Updated to:
import random
class MonkiesGo:
def __init__(self, targetString):
self.targetString = targetString.lower()
self.targetList = list(targetString)
self.attemptList = []
self.unmatchedIndexes = [ x for x in range(0, (len(targetString)-1)) ]
self.chars = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
def attemptToSolve(self):
if len(self.unmatchedIndexes) == 0:
self.attemptString = ''.join(self.attemptList)
return self.attemptString, self.targetString
else:
for index in self.unmatchedIndexes:
self.attemptList[index] = randomChar()
def updateSolutionProgress(self):
for indexCheck in self.unmatchedIndexes:
if self.targetList[index] == self.attemptList[index]:
indexToClear = self.unmatchedIndexes.index(index)
del self.unmatchedIndexes[indextToClear]
def randomChar(self):
return self.chars[ random.randint(0,26) ]
Now I get a name error regarding randomChar..?
You are not creating any instance variables. In the function __init__, variables such as __targetString are local and are defined only within the function. When you call the function attemptToSolve, the variable __unmatchedIndices is also local and therefore undefined. The double underscore does not automatically make an instance variable; perhaps that's your confusion.
Instead of __targetString = whatever, you should use self.__targetString = whatever, or better yet drop the underscores and use just self.targetString. That creates a member variable. Access it in member functions using the same self.targetString syntax. Check out the tutorial that comes with Python.

Using import random, using random.choice throws AttributeError

So, I'm getting a really weird error. For some reason python is not importing random as the module, and seems to me to be importing it as a function (as seen here). Why is it doing this? Using import random and random.choice() works fine in other modules. Why not here?
update: Turns out I was defining random again in logic.py. I had forgot I did this since I wasn't using it anymore. Commented it out and it works fine.
Traceback:
Traceback (most recent call last):
File "H:\workspace37\RockPaperScissors\irps\driver.py", line 20, in <module>
print "%r" % dtree.root.get_value(history)
File "H:\workspace37\RockPaperScissors\irps\datastructures.py", line 69, in get_value
return self.operation(self.left.get_value(history), self.right.get_value(history))
File "H:\workspace37\RockPaperScissors\irps\datastructures.py", line 69, in get_value
return self.operation(self.left.get_value(history), self.right.get_value(history))
File "H:\workspace37\RockPaperScissors\irps\logic.py", line 53, in either
return random.choice((a, b))
AttributeError: 'function' object has no attribute 'choice'
I've tried to include the relevant bits of code.
logic.py:
import random
#from random import choice # works if I change random.choice(...) to just choice(...)
ROCK = 'R'
PAPER = 'P'
SCISSORS = 'S'
RPS_TUPLE = (ROCK, PAPER, SCISSORS)
RPS_SET = set((ROCK, PAPER, SCISSORS))
PLAYER = 0
OPPONENT = 1
PLAYERS = (PLAYER, OPPONENT)
def assert_in_set(a, b):
assert a in RPS_SET
assert b in RPS_SET
def neither(a, b):
assert_in_set(a, b)
diff = RPS_SET.difference((a, b))
print "diff = ", diff
return random.choice(tuple(diff))
def either(a, b):
assert_in_set(a, b)
return random.choice((a, b)) #line 53
#EDITED TO INCLUDE THESE LINES FURTHER DOWN
def random(a, b):
return random.choice(RPS_TUPLE)
ALL_OPERATORS = (neither, either)
datastructures.py
from collections import deque
from logic import RPS_TUPLE, ALL_OPERATORS, PLAYERS
import random
import sys
class OperationNode(TreeNode):
def __init__(self, parent, left, right, operation):
super(OperationNode, self).__init__(parent, left, right)
self.operation = operation
def get_value(self, history):
return self.operation(self.left.get_value(history), self.right.get_value(history)) # line 69
class TerminalNode(TreeNode):
def __init__(self, parent, player, position):
super(TerminalNode, self).__init__(parent, None, None)
self.player = player
self.position = position
def get_value(self, history):
# history is a deque of tuples
return history[self.position][self.player]
Did you define random function in logic.py?
That could be a cause of a problem.
>>> def random():
... pass
...
>>> random.choice
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'choice'

Categories