Python - Calling a definition inside a class within another file - python

I am currently working on the framework for a simple turn based game. I am trying to call a definition within a class Inside of a separate file from my current one. The Program I am importing the moveset file from is called Pymon_Movesets. I am importing it into the Pymon_Main file. The code for both looks a little like this...
(Pymon_Moveset)
class normaltype():
def scratch():
type = normal
slot = 1
# Base normal type move
damage = 2 * level/2
Pymon_Main
From Pymon_Movesets import *
def Initialize():
Scratch = Pymon_Movesets.normaltype.scratch()
Bite = Pymon_Movesets.normaltype.bite()
My Error
File "C:\Users\samsc\Desktop\Pymon\Pymon_main.py", line 2, in <module>
from Pymon_Movesets import * File "C:\Users\samsc\Desktop\Pymon\Pymon_Movesets.py", line 3, in <module>
import Pymon_main File "C:\Users\samsc\Desktop\Pymon\Pymon_main.py", line 110, in <module>
gamefunction.Initialize() File "C:\Users\samsc\Desktop\Pymon\Pymon_main.py", line 26, in Initialize
Scratch = Pymon_Movesets.normaltype.scratch() AttributeError: module 'Pymon_Movesets' has no attribute 'normaltype' The program
'[4908] python.exe' has exited with code -1073741510 (0xc000013a).
I am Using Visual Studios Python Editor.
Thank you for your time

You are importing all the contents of Pymon_Moveset.py into the current namespace, however, you still call the class using the filename. Also, you need to create an instance of the class before you call a method. Lastly, you need to include self in the method signature, so it is bound to the class:
In Pymon_Movesets:
class normaltype():
def scratch(self):
type = normal
slot = 1
# Base normal type move
damage = 2 * level/2
In main file:
import Pymon_Movesets
def Initialize():
Scratch = Pymon_Movesets.normaltype().scratch()
Bite = Pymon_Movesets.normaltype().bite()
However, if you want to access the methods in the class using the name of the class and not an instance, use staticmethod:
In Pymon_Moveset.py:
class normaltype():
#staticmethod
def scratch():
type = normal
slot = 1
# Base normal type move
damage = 2 * level/2

Since you're doing from Pymon_Movesets import *, no need to use Pymon_Movesets to call its normaltype function if it is a module-level / file-level function.
from Pymon_Movesets import *
def Initialize():
Scratch = normaltype.scratch()
Bite = normaltype.bite()

Related

How to call SCons global function from a helper-script called by a SConscript?

I have some non-trivial logic necessary to compute the paths to certain source & header file directories and since it applies to multiple SConscripts I put it in a separate .py file, imported from each SConscript that needs it. Now I need to be able to call a SCons global function (in this case, the Glob function) from within the helper-script. Previously that function was callable directly from within the SConscripts, but now that I need to call it from the separate helper-script I can't figure out how to call it. I suppose this is probably trivial but I'm really not very familiar with Python.
UPDATE:
It seems the ability to call Glob() as a "global function" has something to do with some trickery that SCons is playing. Here's an excerpt from the main entry file (SConscript.py, which is not the same as the SConscripts that we pepper all over our source tree):
_DefaultEnvironmentProxy = None
def get_DefaultEnvironmentProxy():
global _DefaultEnvironmentProxy
if not _DefaultEnvironmentProxy:
default_env = SCons.Defaults.DefaultEnvironment()
_DefaultEnvironmentProxy = SCons.Environment.NoSubstitutionProxy(default_env)
return _DefaultEnvironmentProxy
class DefaultEnvironmentCall(object):
"""A class that implements "global function" calls of
Environment methods by fetching the specified method from the
DefaultEnvironment's class. Note that this uses an intermediate
proxy class instead of calling the DefaultEnvironment method
directly so that the proxy can override the subst() method and
thereby prevent expansion of construction variables (since from
the user's point of view this was called as a global function,
with no associated construction environment)."""
def __init__(self, method_name, subst=0):
self.method_name = method_name
if subst:
self.factory = SCons.Defaults.DefaultEnvironment
else:
self.factory = get_DefaultEnvironmentProxy
def __call__(self, *args, **kw):
env = self.factory()
method = getattr(env, self.method_name)
return method(*args, **kw)
def BuildDefaultGlobals():
"""
Create a dictionary containing all the default globals for
SConstruct and SConscript files.
"""
global GlobalDict
if GlobalDict is None:
GlobalDict = {}
import SCons.Script # <-------This is referring to a directory with a file named __init__.py, which I've learned is something special in Python
d = SCons.Script.__dict__
def not_a_module(m, d=d, mtype=type(SCons.Script)):
return not isinstance(d[m], mtype)
for m in filter(not_a_module, dir(SCons.Script)):
GlobalDict[m] = d[m]
return GlobalDict.copy()
So I thought perhaps I need to import SCons.Script in my helper-script:
import SCons.Script
Unfortunately I still get this:
NameError: name 'Glob' is not defined:
File "D:\Git\......\SConstruct", line 412:
SConscript(theSconscript, duplicate=0)
File "c:\python37\lib\site-packages\scons\SCons\Script\SConscript.py", line 671:
return method(*args, **kw)
File "c:\python37\lib\site-packages\scons\SCons\Script\SConscript.py", line 608:
return _SConscript(self.fs, *files, **subst_kw)
.
.
.
File "D:\Git\........\SConscript", line 433:
.
.
.
File "D:\Git\............\PathSelector.py", line 78:
src_files.extend(Glob((os.path.join(src_path_a, '*.c')), strings=1))
From the manpage:
Global functions may be called from custom Python modules that you import into an SConscript file by adding the following import to the Python module:
from SCons.Script import *

Python set self-variables by other class using cls?

I wonder if it is possible to set variables of a class by a different class using cls?
The story behind it:
I'm writing tests for different purposes but see that one part of the setup is the same as in an already existing class. So I would do the setUp by the already existing one:
The original code:
class TestBase(unittest.TestCase):
def setUp(self):
self.handler = txt.getHandler(hcu.handler3())
self.curves = self.handler.curves()
self.arguments = (getInit())
self.ac = self.connect2DB(self.arguments)
self.au = AutoUtils()
This has worked well so far.
Now in my TestClient I'd like to make use of that:
from .testsDB import TestBase as tb
class TestClient(unittest.TestCase):
def setUp(self):
tb.setUp()
And modified in the TestBase the setUp to the following:
#classmethod
def setUp(cls):
cls.handler = txt.getHandler(hcu.handler3())
cls.graph = cls.handler.curves()
cls.argv = (getInit())
cls.ac = cls.connect2DB(cls.arguments)
cls.au = AutoUtils()
But I'm getting an error as soon as I use one of the values defined in the variables of the TestClient-class:
def test_Duplicates(self):
self.testDB = self.ac.connect(self.ac.client, self.arguments[4])
With the error:
In test_Duplicate (Curves.tests_client.TestClient) :
Traceback (most recent call last):
File "/home/qohelet/Curves/tests_client.py", line 49, in test_Duplicate
self.testDB = self.ac.connect(self.ac.client, self.arguments[4])
AttributeError: 'TestClient' object has no attribute 'ac'
Is it actually possible what I'm trying?
EDIT:
After writing this and seeing the answers I did another review. Yes indeed there is a circular issue I'm having.
TestBase has the function connect2DB which will be executed on setUp.
If it refers to itself (as in the original) it's fine.
If I replace the self with cls it will try to execute TestClient.connect2DB in the setUp - which does not exist. So it would require self again as putting connect2DB into TestClient is not an option.
How to solve that?
Surely your new class should just inherit the setup()?
from .testsDB import TestBase as tb
class TestClient(tb):
def test_Duplicates(self):
self.testDB = self.ac.connect(self.ac.client, self.arguments[4])
The whole point of inheritance is that you don't modify what you inherit from. Your new class should just make use of what is supplied. That is why inheritance is sometimes called programming by difference.

user defined class serialization and deserialization in python

I am very new to python : I want to serialize and deserialize my custom object in python. Please guide me on the same. I have a sample class :
import pickle
import json
class MyClass():
variable = "blah"
num = 10
def function(self):
print("this is a message inside the class.")
def get_variable():
return variable
def get_num():
return num
def main():
myObj = MyClass()
with open('/opt/infi/deeMyObj.txt', 'w') as output:
pickle.dump(myObj, output,pickle.HIGHEST_PROTOCOL)
with open('/opt/infi/deeMyObj.txt', 'r') as input:
myObjread = pickle.load(input)
print myObjread.get_variable()
print myObjread.get_num()
main()
I am getting following error :
Traceback (most recent call last):
File "sample.py", line 30, in
main()
File "sample.py", line 27, in main
print myObjread.get_variable()
TypeError: get_variable() takes no arguments (1 given)
Main intention is to read the object back.
To expand on jasonharper's comment, your get_variable and get_num methods aren't referring to the class's member variables. They should take the object as their first argument, e.g.
class MyClass:
...
def get_variable(self):
return self.variable
I think your serialization code is OK, but I might be wrong.
(Aside)
This is a bit off-topic, but another thing to note: when you define variables directly within the class block, they're defined on the class, not on objects of that class. That happens to work out in this case, since Python will look for a class-level variable of the same name if it can't find one on the object. However, if you store, say, a list in one of them and start modifying it, you'd end up sharing it between objects, which is probably not what you want. Instead you want to define them on in an __init__ method:
class MyClass:
def __init__(self):
self.variable = "blah"

Use other class functions in another class without creating a new instance

I am trying to develop a robot for Skype and I am having difficulties with certain classes and how to use only one instance instead of creating a new one within another file.
I have many files in which the robot runs from and I want to only use one instance via a Global.py file:
from classes import class_Core
from classes import class_Skype
from classes import class_Message
from classes import class_Commands
global Core, Skype, Message, Commands
Core = class_Core.Core()
Skype = class_Skype.Skype()
Message = class_Message.Message()
Commands = class_Commands.Commands()
I also have a Skypebot.py file which imports the Global.py file:
import Global
However, when I run Skypebot.py and use a function from Core in the Skype class:
class Skype:
def __init__(self):
Core.Log("Initialising Skype!")
I get an trace back:
Traceback (most recent call last):
File "C:\Users\Connor\Desktop\Skypebot 0.4\Skypebot.py", line 1, in <module>
import Global
File "C:\Users\Connor\Desktop\Skypebot 0.4\Global.py", line 9, in <module>
Skype = class_Skype.Skype()
File "C:\Users\Connor\Desktop\Skypebot 0.4\classes\class_Skype.py", line 8, in
__init__
Core.Log("Initialising Skype!")
NameError: global name 'Core' is not defined
Can anybody help me on this? Thanks!
You want this in skypebot.py, instead of import Global:
from Global import Core
You also don't need the global Core, Skype, Message, Commands line, since those variables are already being declared at a global scope within Global.py, as doukremt mentioned. The "global" keyword would be used if you then wanted to access/modify a global variable instance a function or method, e.g.
var = 3
def some_func():
var = 2 # This creates a locally-scoped variable named var, and assigns it to 2.
def some_other_func():
global var
var = 2 # This sets the globally-scoped variable var to 2.

Using python static class C#/Java style, scope difference errors

I have two files, namely game.py and map.py. The following simplified code resides in them:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from datetime import *
from map import *
class Game:
Scene = QGraphicsScene
View = QGraphicsView
#staticmethod
def start():
Game.App = QApplication(sys.argv)
Game.Scene=QGraphicsScene();
Game.Scene.setBackgroundBrush(QBrush(QColor(Qt.green)));
Game.View=QGraphicsView(Game.Scene);
print Game
map=Map()
Game.App.exec_()
if __name__=='__main__':
Game.start()
and file map.py:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from game import *
class Map(QObject):
def __init__(self,parent=None):
super(Map,self).__init__(parent);
print Game
v=Game.View
print v
v.setWindowTitle("sth")
Running game.py results in
__main__.Game
game.Game
<class 'PyQt4.QtGui.QGraphicsView'>
Traceback (most recent call last):
File "/home/abiusx/workspace/borj/trunk/game.py", line 119, in <module>
Game.start()
File "/home/abiusx/workspace/borj/trunk/game.py", line 66, in start
map=Map()
File "/home/abiusx/workspace/borj/trunk/map.py", line 16, in __init__
v.setWindowTitle("asb")
TypeError: QWidget.setWindowTitle(QString): first argument of unbound method must have type 'QWidget'
The problem is, the code in map.py that references Game.View, detects it as a class (as defined in class body) but not what is overwritted on it (an actual instance).
Also Game is known as main.Game in game.py but as game.Game in map.py
Could anyone help me?
the code in map.py that references Game.View, detects it as a class
That's because View = QGraphicsView sets it to a class. It only becomes an instance when you run Game.start. (To be honest, I don't understand why you're setting this class variable to a class object initially, or why the Game class exists at all.)
Also Game is known as main.Game in game.py but as game.Game in map.py
The module name changes to __main__ when you run a module as a script.
Whenever a file is read in Python, when it reaches a class definition it defines that class.
In my scenario, game and map both relied on each other. this is a well known circular reference problem in python.
I added another module, main.py, used game and map in it, and game in map. Problem solved.

Categories