Call specific variable in function - python

Somebody can help me how to access specific variable from other function in Python?
class A:
me = None
def __init__(self):
self.me = self.me
def something(self, other):
other = other
self.me = "its me to change"
return other #this function just return 'other' only.
def call_me(self):
something = A().something
print something.__get__(self.me) #get variable 'self.me' only from function of 'something'
A().call_me()
We need only show self.me in my function of call_me(self):
So, if we call A().call_me(), the output is its me to change.
Edit:
class A:
def something(self, other):
other = other
me = "its me to change"
return other
def call_me(self):
something = A().something
#get variable 'me' only from function of something
A().call_me()

Looks like you did not fully understand how Python objects work.
class A:
me = None
Here, you declare a attribute of class A, what would be called a static attribute in other OO languages => it is shared between all objects of the class
class A:
...
def __init__(self):
self.me = self.me
Almost a no-op: you override the static attribute A.me with an object attribute with same name and same value. The only effect if that when you create an object of class A it has a private copy:
>>> a = A()
>>> id(a.me) = id(A.me) # same value ?
True
>>> id(a.me) is id(A.me) # same object
False
Let's continue
class A:
...
def something(self, other):
other = other
self.me = "its me to change"
return other #this function just return 'other' only.
other = other is really a no-op
self.me = ... sets the value of the object attribute me - you can now access this new value in any other method as self.me or from the outside as a.me (if a is an object of class A) - if would be the same even if you had not done self.me = self.me in __init__
Last but not least:
class A:
...
def call_me(self):
something = A().something
print something.__get__(self.me) # ???
something = A().something: declares a new object of class A and make the local variable something point to the something method of that object - as the variable is local to the method, that new object will be destroyed on method exit
print something.__get__(self.me): does nothing, as you never call the something method, so just display, so you get:
>>> a = A() # create an object a of class A
>>> a.call_me() # call call_me method on that object
<bound method A.something of <__main__.A instance at ...>>
>>> A().call_me() # directly call `call_me` on a temporary object
...
TypeError: __get__(None, None) is invalid
because in first case you just print the local variable something as self is a valid object (a), while in second case it is just a temporary
I assume that want you wanted is simply:
class A:
def something(self, other):
self.me = "its me to change" # sets the attribute 'me'
return other #this function just return 'other' only.
def call_me(self):
self.something(None) # call something on self => sets self.me
print self.me #get variable 'self.me' after setting it in 'something'
You get now as expected:
>>> A().call_me()
its me to change

Related

Create an object from a python function returns a class

I have a function which returns a class:
def my_function():
# some logic
class AClass:
def __init__(self, argument):
init()
return AClass
And when I call this function, it returns a class, not an object of that class, right?
Value = my_function()
My question is how can I create an object from that class AClass?
Thank you.
my_class = my_function()
my_obj = my_class(arg)
Since the method returns a reference to a type you can simply use whatever constructor that is defined for the class directly on the return value.
Take this class for example:
class A:
def __init_(self, n = 0):
self.__n = n
Lets see what happens when reference the type directly when running the interpreter interactively:
>>> A
<class `__main__.A`>
Now lets return the type in a method:
>>> def f():
>>> return A
>>> f()
<class `__main__.A`>
Since the value of referencing the class directly and when returned from a method is the same, you can use that returned value the same you would normally. Therefore a = A() is the same as a = f()(). Even if the class takes parameter you can still reference it directly: a = f()(n = 10)

Re-defining already assigned python class

I am new to Python and I inherited someone's code that had the following code structure. Why do I get an object not callable and how can I redefine this method again even after re-assigning l.bar. Another question would therefore be what's the difference between l.bar and l.bar()?
>>> class foo(object):
... def __init__(self):
... self.name = "Food"
... class bar(object):
... def __init__(self):
... self.name = "Is"
... class tea(object):
... def __init__(self):
... self.name = "Good"
...
>>> l = foo()
>>> m = l.bar()
>>> m.name = "Was"
>>> l.bar = m
>>> r = l.bar()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'bar' object is not callable
As others have pointed out, it's generally not good practice to have nested classes. But, here's a breakdown of what's happening:
class foo(object):
def __init__(self):
self.name = "Food"
class bar(object):
def __init__(self):
self.name = "Is"
class tea(object):
def __init__(self):
self.name = "Good"
l = foo() # l is now an instance of foo
print l.name # "Food"
m = l.bar() # m is now an instance of bar
print m.name # "Is"
m.name = "Was" # you've assigned m's name to "Was"
print m.name # "Was"
l.bar = m # you are overriding foo's nested bar class now with an instance of bar
print l.name # "Food"
print l.bar # <__main__.bar object at 0x108371ad0>: this is now an instance, not a class
print l.bar.name # "Was"
r = l.bar() # you are now trying to call an instance of bar
The last line doesn't work because of the same reasons calling l() or foo()() doesn't work.
If you absolutely must figure out a way to make foo.bar().name return something else, you can create a new class and reassign foo.bar to it. But, this is really gross and not recommended. Hopefully, you can just change that original code.
print foo.bar().name # "Is"
class NewBar(object):
def __init__(self):
self.name = 'Was'
foo.bar = NewBar
print foo.bar().name # "Was"
Why do i get an object not callable
You assigned l.bar to be an instance of the class foo.bar (specifically, you assigned m to it). Instances of that class aren't callable, therefore l.bar isn't callable.
how can i redefine this method again even after re-assigning l.bar
Maybe this advice is too obvious, but don't re-assign l.bar.
However, you can reset l.bar so that it refers to the method it originally referred to, by doing del l.bar.
The reason this works is because if the individual object has no bar attribute of its own, then Python looks next to see whether its class has an attribute of the same name. So, to begin with the expression l.bar evaluates to the class foo.bar, since l has type foo. Then you assigned l a bar attribute of its own, so l.bar suddenly starts evaluating to that object instead. You can restore normality by deleting the object's own attribute.
what's the difference between l.bar and l.bar()
l.bar just gets the value of the attribute bar from the object l (or from its class, if the object l doesn't have one of its own, as explained above. If that fails too it'd go to base classes). l.bar() gets the value of that attribute and then calls it. () at this position means a function call, so the thing you put it after had better be callable.
It is not clear which of the following problems you are experiencing:
1. indentation issue
When copy-pasting from source to terminal, indentation sometimes gets messed up. in ipython you can use %paste to safely paste code.
The correctly indented class declarations are:
class foo(object):
def __init__(self):
self.name = "Food"
class bar(object):
def __init__(self):
self.name = "Is"
class tea(object):
def __init__(self):
self.name = "Good"
But then the other commands make no sense.
2. instance is not the same as class
When defining a class inside a class, you have to use the outer class name to "get" to the inner class name. I.e.:
class foo(object):
def __init__(self):
self.name = "Food"
class bar(object):
def __init__(self):
self.name = "Is"
class tea(object):
def __init__(self):
self.name = "Good"
foo_inst = foo()
bar_inst = foo.bar()
tea_inst = foo.bar.tea()
Anyhow, these lines still make not much sense:
>>> l.bar = m
>>> r = l.bar()
Why would you want to override bar which is (was) a class name...

How to override a method of a member object?

In python 3.4 I have a member object through composition.
I would like to override one of it's member functions.
def class Foo:
def __init__(self, value):
self.value = value
def member_obj.baz(baz_self, arg):
print("my new actions on {}".format(arg))
Foo.member_obj.baz(arg) #the original function
foo_inst = Foo(2)
bar = Bar(*bar_parameters) #from a third party module
setattr(foo_inst, "member_obj", bar) #it did not "stick" when I did foo_inst.member_obj = bar
foo_inst.member_obj.baz("some argument")
It does not make sense to inherit from the Bar class.
I also only want this different behaviour to occur if the object is inside Foo. I use Bar in many other places and would like to retain the same way of calling the method. I.e. I would like to avoid wrapping it in Foo.baz.
Is it even possible to do something like the def member_obj.baz and is it a good idea?
It would be similar to this: https://softwareengineering.stackexchange.com/questions/150973/what-are-the-alternatives-to-overriding-a-method-when-using-composition-instea
Are you trying to do something like this?
class B():
def __init__(self):
self.x = None
def fun(self):
print("Assigning value to attribute of object of class B.\n")
self.x = "Value of B object's attribute"
class A():
def __init__(self):
self.value = B()
def fun(self):
print("Screw this, I'll do something else this time!\n")
self.value.x = 13
def override(self):
# Edit: you can assign any identifier (that is not reserved) to
# any type of object or method AND the "fun" ("really self.fun")
# above is visible from here, since we passed "self" as an
# argument
self.value.fun = self.fun
myObj = B()
myOtherObj = A()
myOtherObj.override()
myObj.fun()
myOtherObj.value.fun()

How can the name of a class be set automatically in a data attribute of an instance of that class in Python?

How can the name of a class be set automatically in a data attribute of an instance of that class?
Here is some example code:
def workFunctionTest(**kwargs):
time.sleep(3)
return kwargs
def printHR(object):
# dictionary
if isinstance(object, dict):
for key, value in sorted(object.items()):
print u'{0}: {1}'.format(key, value)
# list or tuple
elif isinstance(object, list) or isinstance(object, tuple):
for element in object:
print element
# other
else:
print object
class Job(object):
def __init__(
self,
workFunction=workFunctionTest,
workFunctionArguments={'testString': "hello world"},
naturalLanguageString=None
):
self.workFunction=workFunction
self.workFunctionArguments=workFunctionArguments,
self.naturalLanguageString=naturalLanguageString
def printout(self):
"""
This method prints a dictionary of all data attributes.
"""
printHR(vars(self))
def main():
job1=Job(
workFunction=workFunctionTest,
workFunctionArguments={'testString': "hello world"},
)
print("Is the object an instance of the class?")
print isinstance(job1, Job)
print("a printout generated by a method of the object:")
job1.printout()
if __name__ == '__main__':
main()
How could the end of the printout from this code be changed from this:
naturalLanguageString: None
workFunction: <function workFunctionTest at 0x7f435461ac80>
workFunctionArguments: ({'testString': 'hello world'},)
to this?:
naturalLanguageString: Job
workFunction: <function workFunctionTest at 0x7f435461ac80>
workFunctionArguments: ({'testString': 'hello world'},)
self.naturalLanguageString = naturalLanguageString or self.__class__.__name__
this should work
if you do not pass the naturalLanguageString, it will be set by default with the class name
I think you are looking for self.__class__.__name__.
You can do this:
self.naturalLanguageString = self.__class__.__name__
As extra you can access ALL the class whit self.__class__
You're probably looking for:
naturalLanguageString = type(self).__name__

removing a property in python

I am using a code snippet from here along with my own modifications in ironpython which works extremly well:
from System.ComponentModel import INotifyPropertyChanged, PropertyChangedEventArgs
from Library.pyevent import make_event
class Notify_property(property):
''' defines a notifiable property
'''
def __init__(self, getter):
def newgetter(slf):
#return None when the property does not exist yet
try:
return getter(slf)
except AttributeError:
return None
super(Notify_property, self).__init__(newgetter)
def setter(self, setter):
def newsetter(slf, newvalue):
# do not change value if the new value is the same
# trigger PropertyChanged event when value changes
oldvalue = self.fget(slf)
if oldvalue != newvalue:
setter(slf, newvalue)
slf.OnPropertyChanged(setter.__name__)
return property(
fget=self.fget,
fset=newsetter,
fdel=self.fdel,
doc=self.__doc__)
class NotifyPropertyChangedBase(INotifyPropertyChanged):
''' The base of the MVVM view model
Here the bound properties are added in addition with its
handlers.
'''
# handlers which get fired on any change register here
PropertyChanged = None
''' handlers that only get fired on their property change register here
they are organized in a dictionary with the property name as key and
a list of handlers as value
'''
_property_handlers = {}
def __init__(self):
''' we create an event for the property changed event
'''
self.PropertyChanged, self._propertyChangedCaller = make_event()
def add_PropertyChanged(self, value):
''' helper function to wrap the += behaviour
'''
self.PropertyChanged += value
def remove_PropertyChanged(self, value):
''' helper function to wrap the -= behaviour
'''
self.PropertyChanged -= value
def OnPropertyChanged(self, propertyName):
''' gets fired on an property changed event
'''
if self.PropertyChanged is not None:
self._propertyChangedCaller(self, PropertyChangedEventArgs(propertyName))
try:
for property_handler in self._property_handlers[propertyName]:
property_handler(propertyName,PropertyChangedEventArgs(propertyName))
except KeyError:
pass
def add_notifiable_property(self, notifiable_property):
self.add_handled_property((notifiable_property,None))
def add_notifiable_property_list(self, *symbols):
for symbol in symbols:
self.add_notifiable_property(symbol)
def add_handled_property_list(self, *symbols):
for symbol in symbols:
self.add_handled_property(symbol)
def add_handled_property(self, notifiable_property):
symbol = notifiable_property[0]
if notifiable_property[1] is not None:
self._property_handlers[notifiable_property[0]] = notifiable_property[1]
dnp = """
import sys
sys.path.append(__file__)
#Notify_property
def {0}(self):
return self._{0}
#{0}.setter
def {0}(self, value):
self._{0} = value
""".format(symbol)
d = globals()
exec dnp.strip() in d
setattr(self.__class__, symbol, d[symbol])
Now I must admit that I not fully understand all of the code. Mainly the use of the Notify_property class is an enigma to me. To get a better understanding of the code I tried to remove a property. Calling from my MainViewModel which subclasses the above class I can define a property via:
add_notifiable_property('TestProperty')
or
add_handled_property((TestProperty,[handler1,handler2])
I can also delete handlers (not yet implemeted) but how to I remove a property again?
del self.TestProperty
excepts with
undeletable attribute
and
delattr(self,'TestProperty')
excepts with
delattr takes exactly 2 arguments 2 given
hmm very strange.
I also tried to add a function to my base class:
def remove_notifiable_property(self,propertyname):
''' removes a notifiable property
'''
self._property_handlers.pop(propertyname,None)
exec "del self.{0}".format(propertyname)
but get the same error about an undeletable attribute.
How can I remove a set property again?
EDIT: I found out I was missing the deleter function. Adding this code to the above dnp string now leads to a new error:
#{0}.deleter
def {0}(self):
del self._{0}
with new error:
Derived calss has no attribute _TestProperty
with TestProperty being the name I added. Still stuck.
EDIT2:
I tracked it down to the following:
class C(object):
def __init__(self):
pass#self._x = None
#property
def x(self):
"""I'm the 'x' property."""
return self._x
#x.setter
def x(self, value):
self._x = value
#x.deleter
def x(self):
del self._x
c = C()
print dir(c)
c.x = 'A'
print c.x
print dir(c)
del c.x
print dir (c)
shows the same behavior. The error no _ came from missing initializing the attribute. Adding an:
exec """self._{0} = None""".format(symbol)
to the last line of the add_handled_property fixes it.
But still the attribute itself is shown with dir, also it is not in the class anymore. Is this a bug in python?
You should be able to do
delattr(self.__class__, 'TestProperty')
because the properties are in the class's __dict__. See the last line:
setattr(self.__class__, symbol, d[symbol])
Example of how properties work in Python using the class A, instance a and property p in the class A:
>>> class A(object):
class Property(object):
def __get__(*args):
print 'get:', args
def __set__(*args):
print 'set:', args
def __delete__(*args):
print 'del:', args
p = Property()
>>> A.p
get: (<__main__.Property object at 0x7f3e16da4690>, None, <class '__main__.A'>)
>>> a = A()
>>> a.p
get: (<__main__.Property object at 0x7f3e16da4690>, <__main__.A object at 0x7f3e16da4910>, <class '__main__.A'>)
>>> a.p = 3
set: (<__main__.Property object at 0x7f3e16da4690>, <__main__.A object at 0x7f3e16da4910>, 3)
>>> del a.p
del: (<__main__.Property object at 0x7f3e16da4690>, <__main__.A object at 0x7f3e16da4910>)
you can replace them in the class
>>> A.p = 2
>>> a.p
2
or delete them from the class
>>> A.p = A.Property()
>>> del A.p

Categories

Resources