i have a dll function of some api like this:
def dllcallback(items):
pass
i want to access self in class functions linked with dll callback.
class myobject(object):
def __init__(self):
self.a = 999
#dllcallback
def mycallback(self, items):
print (self.a)
self.a = 888
print (self.a)
i don't think dllcallback accepts self as argument. so this was fail.
i wish myobject.mycallback will trigger when dllcallback is called by api, and shows:
999
888
and i tried the below to make 'self' be accessible by inner functions, but this approach killed the Kernel...
class myobject(object):
def __init__(self):
self.a = 999
def callbacks(self):
#dllcallback
def mycallback(items):
print (self.a)
self.a = 888
print (self.a)
i am not sure the reason why the kernel died. thanks in advance for any suggestion.
UPDATED: 20180912 1436
Actually, the override method could be called without self as argument,
class myobject(object):
def __init__(self):
self.a = 999
#dllcallback
def mycallback(items):
global self
print (self.a)
self.a = 888
print (self.a)
NameError: name 'self' is not defined
I suppose 'self' cannot be obtained like this...any suggestions?
UPDATED: 20180913 1645
Got some progress in writing a class including ctypes dll callback functions
class myobject(object):
def __init__(self):
if u'32bit' in architecture(): # 32bit WinOS
self.spdll = windll.LoadLibrary('XXX.dll')
else: # 64bit WinOS
self.spdll = cdll.LoadLibrary('XXX.dll')
self.a = 999
def callbacksinit(self):
def mycallback(items):
print (self.a)
self.a = 888
print (self.a)
self.mycallbackaddr = WINFUNCTYPE(None, c_char_p)
def regcallbacks(self):
self.spdll.APICALLBACK(self.mycallbackaddr)
With this code, i can access self.a when mycallback is triggered by API.
And fortunately for me, self.a can be changed to 888 after mycallback is done without global declaration (e.g. global self) in mycallback.
I have no idea why this happens...why WINFUNCTYPE(None, c_char_p) works in this way and why self.a can be changed without global declaration. I leave this question open a while and maybe someone can clear my doubts.
Your update is a valid solution. You can update self because it is mutable. You don't need a global (or in this case, nonlocal) declaration to access it. You only need those to reassign the variable.
For example:
def func():
L = []
def inner():
#nonlocal L # Uncomment to work
L = [1,2,3] # Reassign L
inner() # Call the function and attempt to modify L
return L
def func2():
L = []
def inner():
L[:] = [1,2,3] # Mutate L
inner() # Call the function and attempt to modify L
return L
print(func())
print(func2())
Output:
[]
[1, 2, 3]
Here's a full working example of your approach...
test.c
#include <wchar.h>
#define API __declspec(dllexport)
typedef void (*CALLBACK)(const wchar_t*);
API void do_callback(CALLBACK cb)
{
cb(L"one");
cb(L"two");
cb(L"three");
}
test.py
from ctypes import *
CALLBACK = CFUNCTYPE(None,c_wchar_p)
class Test:
dll = CDLL('test')
dll.do_callback.argtypes = CALLBACK,
dll.do_callback.restype = None
def __init__(self):
self.count = 0
def get_callback(self):
#CALLBACK
def callback(s):
self.count += 1 # nonlocal, but mutable
print(self.count,s)
return callback
def do(self):
self.dll.do_callback(self.get_callback())
t = Test()
t.do()
Output:
1 one
2 two
3 three
Python has a magic way to find the method+instance in a callback. But when you're interfacing with another language, that's another story.
Not sure if you can do better than:
registering your object in a global (well, class-instance) dictionary
create a callback wrapping function that finds the id (that your caller has to know) and calls the method with the proper context
You can keep all static objects inside the class scope for a cleaner solution.
like this:
class myobject(object):
globdict = {}
id = 0
def __init__(self):
self.a = 999
self.id += 1 # this id will have to be passed to the foreign library
myobject.globdict[self.id] = self
def mycallback(self, items):
print (self.a)
#staticmethod
def real_callback(id,items):
# first parameter is the object, then the "items" argument
# using function-call style (not object)
# id may need to be converted back from `ctypes`
myobject.mycallback(myobject.globdict[id],items)
Related
When you are debugging complex code, you sometimes need to transform:
def myfunction(self):
...
self.foo.bar = self.baz.bla
into
def myfunction(self):
...
self.foo.bar = self.baz.bla
print("myfunction", "self.foo.bar", self.foo.bar) # add this for debugging purposes
Is there a way (with a decorator or context manager or anything else) to automatically print the variable name and the value of the next line of code's assignement (and maybe also the current function)?
Example:
def myfunction(self):
...
with debug:
self.foo.bar = self.baz.bla
would output:
"myfunction self.foo.bar 123"
You can use the inspect module:
from inspect import currentframe
def f():
a = 5
debug_print("a")
def debug_print(var):
locals = currentframe().f_back.f_locals
print(f"{var} = {locals[var]}")
f()
See also here: Access parent namespace in python
I admit, it's only part of what you asked, but maybe a good start.
Edit: Ok what about this:
from inspect import currentframe, getsourcelines
class A:
def f(self):
self.b = 5
debug_print()
self.a = A()
self.a.a = 4
debug_print()
#staticmethod
def g():
A.c = 5
debug_print()
def debug_print():
frame = currentframe().f_back
locals = frame.f_locals
globals = frame.f_globals
source, start = getsourcelines(currentframe().f_back.f_code)
var_name = source[frame.f_lineno - 1 - start].split("=")[0]
tokens = var_name.strip().split(".")
var = locals.get(tokens[0], globals.get(tokens[0], None))
for t in tokens[1:]:
var = getattr(var, t)
print(f"{var_name} = {var}")
a = A()
a.f()
a.g()
At least now, it works with member attributes (including self), even nested. Also assignment of global variables, such as static attributes to the class.
A noob confused question,
I have two methods in a class as :
from example import sample2
class sample1:
def m1():
a='apple'
b='ball'
return sample2.m3(a,b)
def m2():
a='ant'
b='bat'
c='cat'
return sample2.m3(a,b,c)
in example.py:
class sample2:
def m3("here I want to access any `a`,`b`,`c` of respective m1 and m2"):
.....
Iam sorry if this question makes no sense, but when I try to access only this as:
class sample1:
def m1():
a='apple'
b='ball'
return sample2.m3(a,b)
in example.py:
class sample2:
def m3(a,b):
print(a)
a has value apple, so similar way why can't I access any value of a,b,c from that particular m1,m2 returned ?
This is how you use decorators. More information how decorator works can be found in for example here: https://www.datacamp.com/community/tutorials/decorators-python
I would suggest you to first try to better understand concept of class and objects. Example tutorial: https://www.w3schools.com/python/python_classes.asp
This post could also help you to understand how staticmethod decorator works - What is the difference between #staticmethod and #classmethod?
from example import sample2
class sample1:
#staticmethod
def m1():
a='apple'
b='ball'
return sample2.m3(a,b)
#staticmethod
def m2():
a='ant'
b='bat'
c='cat'
return sample2.m3(a,b,c)
example.py file with explanation:
class sample2:
#staticmethod
def m3(a, b, c=None): # it works exactly the same as m3 function that is outside the class
print(a)
# this can be used without creating an object of sample2 class, example:
# sample2.m3(a="apple, b="ball")
def m3_method(self, a, b): # this one requires object on which it can be called
print(a)
# you have access to sample2 class object via self parameter, example of code:
# sample2_object = sample2() # you create object of sample2 class here
# sample2_object.m3_method(a="apple", b="ball") # you call m3_method on sample2_object here
def m3(a, b, c=None): # default value of c is add so you can either call it with 2 or 3 arguments
# example calls:
# m3("a", "b")
# m3("a", "b", "c")
print(a)
You should be able to run this code and I think it gives you an idea how Python classes can be used.
Variables in Python always apply to a specific scope, such as a class, function or closure. Python uses lexical scoping, which means scopes are only connected by nesting in the source code. Most importantly, variables in different scopes are not connected at all.
When you "pass a variable" to a function, you are actually passing only the value around. The variable does not exist in other functions (unless they are nested) nor the surrounding scope.
def nested(a):
a = 3
print('a =', a) # a = 3
def parent():
a = 4
nested(a)
print('a =', a) # a = 4
parent()
print(a) # NameError: name 'a' is not defined
Functions should primarily exchange data by calling with input and returning results:
def nested(a): # receive input
a = 3
print('a =', a) # a = 3
return a # return output
def parent():
a = 4
a = nested(a) # replace a with result of nested(a)
print('a =', a) # a = 3
parent()
Note that only values are passed in and returned. The above could would behave exactly the same if you renamed a in either function.
When working with class instances, the instance itself works as a namespace (similar to a scope). Methods of that instance can exchange data by modifying attributes of the instance. The instance is always passed as the first argument to methods:
class Example():
"""An example for setting attributes on an instance"""
def __init__(self):
self.a = 0
def nested(self):
self.a = 3
print('self.a =', self.a) # self.a = 3
def parent(self):
self.a = 4
print('self.a =', self.a) # self.a = 4
self._nested()
print('self.a =', self.a) # self.a = 3
instance = Example()
print(instance.a) # 0
instance.parent() # self.a = 4
# self.a = 3
To exchange data between objects, methods should also primarily exchange data by calling with input and returning results :
class Example():
"""An example for setting attributes on an instance"""
def __init__(self, a):
self.a = a
def multiply(self, value):
return self.a * value
instance = Example(6)
print(instance.multiply(10)) # 60
I want to use the variables i have declared inside a function in one class, in another class.
For example i want to use the variable "j" in another class. Is it possible? (I read somewhere that it might have something to do with instance variables but fully couldn't understand the concept).
class check1:
def helloworld(self):
j = 5
class check1:
def helloworld(self):
self.j = 5
check_instance=check1()
print (hasattr(check_instance,'j')) #False -- j hasn't been set on check_instance yet
check_instance.helloworld() #add j attribute to check_instance
print(check_instance.j) #prints 5
but you don't need a method to assign a new attribute to a class instance...
check_instance.k=6 #this works just fine.
Now you can use check_instance.j (or check_instance.k) just like you would use any other variable.
This may seems a little bit like magic until you learn that:
check_instance.helloworld()
is completely equivalent to:
check1.helloworld(check_instance)
(If you think about it a little bit, that explains what the self parameter is).
I'm not completely sure what you're trying to achieve here -- There are also class variables which are shared by all instances of the class...
class Foo(object):
#define foolist at the class level
#(not at the instance level as self.foolist would be defined in a method)
foolist=[]
A=Foo()
B=Foo()
A.foolist.append("bar")
print (B.foolist) # ["bar"]
print (A.foolist is B.foolist) #True -- A and B are sharing the same foolist variable.
j cannot be seen by another class; however, I think you meant self.j, which can.
class A(object):
def __init__(self, x):
self.x = x
class B(object):
def __init__(self):
self.sum = 0
def addA(self, a):
self.sum += a.x
a = A(4)
b = B()
b.addA(a) # b.sum = 4
Using class inheritane it is very easy to "share" instance variables
example:
class A:
def __init__(self):
self.a = 10
def retb(self):
return self.b
class B(A):
def __init__(self):
A.__init__(self)
self.b = self.a
o = B()
print o.a
print o.b
print o.retb()
class foo():
def __init__(self)
self.var1 = 1
class bar():
def __init__(self):
print "foo var1"
f = foo()
b = bar()
In foo, I am doing something that produces "var1" being set to 1
In bar, I would like to access the contents of var1
How can I access var1 in the class instance f of foo from within the instance b of bar
Basically these classes are different wxframes. So for example in one window the user may be putting in input data, in the second window, it uses that input data to produce an output. In C++, I would have a pointer to the caller but I dont know how to access the caller in python.
As a general way for different pages in wxPython to access and edit the same information consider creating an instance of info class in your MainFrame (or whatever you've called it) class and then passing that instance onto any other pages it creates. For example:
class info():
def __init__(self):
self.info1 = 1
self.info2 = 'time'
print 'initialised'
class MainFrame():
def __init__(self):
a=info()
print a.info1
b=page1(a)
c=page2(a)
print a.info1
class page1():
def __init__(self, information):
self.info=information
self.info.info1=3
class page2():
def __init__(self, information):
self.info=information
print self.info.info1
t=MainFrame()
Output is:
initialised
1
3
3
info is only initialised once proving there is only one instance but page1 has changed the info1 varible to 3 and page2 has registered that change.
No one has provided a code example showing a way to do this without changing the init arguments. You could simply use a variable in the outer scope that defines the two classes. This won't work if one class is defined in a separate source file from the other however.
var1 = None
class foo():
def __init__(self)
self.var1 = var1 = 1
class bar():
def __init__(self):
print var1
f = foo()
b = bar()
Same as in any language.
class Foo(object):
def __init__(self):
self.x = 42
class Bar(object):
def __init__(self, foo):
print foo.x
a = Foo()
b = Bar(a)
Alternatively you could have a common base class from which both derived classes inherit the class variable var1. This way all instances of derived classes can have access to the variable.
Something like:
class foo():
def __init__(self)
self.var1 = 1
class bar():
def __init__(self, foo):
print foo.var1
f = foo()
b = bar(foo)
You should be able to pass around objects in Python just like you pass around pointers in c++.
Perhaps this was added to the language since this question was asked...
The global keyword will help.
x = 5
class Foo():
def foo_func(self):
global x # try commenting this out. that would mean foo_func()
# is creating its own x variable and assigning it a
# value of 3 instead of changing the value of global x
x = 3
class Bar():
def bar_func(self):
print(x)
def run():
bar = Bar() # create instance of Bar and call its
bar.bar_func() # function that will print the current value of x
foo = Foo() # init Foo class and call its function
foo.foo_func() # which will add 3 to the global x variable
bar.bar_func() # call Bar's function again confirming the global
# x variable was changed
if __name__ == '__main__':
run()
I'm writing Python scripts for Blender for a project, but I'm pretty new to the language. Something I am confused about is the usage of static variables. Here is the piece of code I am currently working on:
class panelToggle(bpy.types.Operator):
active = False
def invoke(self, context, event):
self.active = not self.active
return{'FINISHED'}
class OBJECT_OT_openConstraintPanel(panelToggle):
bl_label = "openConstraintPanel"
bl_idname = "openConstraintPanel"
The idea is that the second class should inherit the active variable and the invoke method from the first, so that calling OBJECT_OT_openConstraintPanel.invoke() changes OBJECT_OT_openConstraintPanel.active. Using self as I did above won't work however, and neither does using panelToggle instead. Any idea of how I go about this?
use type(self) for access to class attributes
>>> class A(object):
var = 2
def write(self):
print type(self).var
>>> class B(A):
pass
>>> B().write()
2
>>> B.var = 3
>>> B().write()
3
>>> A().write()
2
You can access active through the class it belongs to:
if panelToggle.active:
# do something
If you want to access the class variable from a method, you could write:
def am_i_active(self):
""" This method will access the right *class* variable by
looking at its own class type first.
"""
if self.__class__.active:
print 'Yes, sir!'
else:
print 'Nope.'
A working example can be found here: http://gist.github.com/522619
The self variable (named self by convention) is the current instance of the class, implicitly passed but explicitely recieved.
class A(object):
answer = 42
def add(self, a, b):
""" ``self`` is received explicitely. """
return A.answer + a + b
a = A()
print a.add(1, 2) # ``The instance -- ``a`` -- is passed implicitely.``
# => 45
print a.answer
# => print 42