I need to convert some code from python 3 to python 2. I have a metaclass where the __prepare__ method sets up a function in the class dict. I tried to translate to a __new__ method but I am unable to set up the SET_DEFAULTS function. Is that possible ?
I have a NameError: name 'SET_DEFAULTS' at initialization
class UazeMessageMeta (type):
#staticmethod
def __prepare__(name, bases, **kwargs):
d = {}
for b in bases:
if 'DEFAULT_VALUES' in dir(b):
d.update(b.DEFAULT_VALUES)
return {
'SET_DEFAULTS' : lambda **kwargs : d.update(kwargs),
'DEFAULT_VALUES' : d
}
class UazeMessage (bytearray):
"""
A basic message (header only). This class also provides the
base behavior for all messages.
"""
# gp test py27 -----------------
__metaclass__ = UazeMessageMeta
# ------------
priority = MessageField(0, 1, Priority)
sequence = MessageField(1, 7, FieldType.UNSIGNED)
readWrite = MessageField(8, 1, ReadWriteFlag)
ack = MessageField(9, 2, Ack)
channel = MessageField(11, 2, FieldType.UNSIGNED)
category = MessageField(13, 3, Category)
item = MessageField(16, 8, FieldType.UNSIGNED)
DEFAULT_SIZE = 3
def __init__(self, init=0, setdefaults=None, **kwargs):
# If init is still or None, initialize the size of the message
# using the default size provided in the class.
if init == None or init == 0:
init = type(self).DEFAULT_SIZE
super(UrmpMessage,self).__init__(init)
# Set any default or provided fields.
initval = {}
if (isinstance(init, int) and setdefaults != False) or \
(setdefaults == True):
initval = dict(self.DEFAULT_VALUES)
initval.update(kwargs)
for key, value in initval.items():
setattr(self, key, value)
class ResetBase (UazeMessage):
"""Reset response/request structure."""
resetType = MessageField(24, 8, ResetType)
SET_DEFAULTS(
category = Category.OPERATION,
resetType = ResetType.SOFT,
item = 0)
DEFAULT_SIZE = 4
Ordinarily, you can't do that.
The introduction of __prepare__ is a fundamental change in Python3, which allows the customization of the namespace where a class body itself is parsed.
I believe the main motivation doing that was to provide a way to replace the local namespace inside a class body with an OrderedDict, so that the class initialization (in the metaclass __new__ or __init__ methods) could benefit from the declaration order of methods and attributes inside the class body. It should be considered that as of Python 3.6 (final version due this week), an ordered dictionary is used by default in the class body, and a metaclass is no longer necessary for that.
The __prepare__ mechanism is way more flexible than that, and in a simpler use, allow one to simply pre-populate the class body dictionary with predetermined values. That is what your project do.
However, since this code does not need an special dictionary class, and just pre-populate an ordinary dictionary, all you need to do is to write an ordinary function that takes in a dictionary and base classes as parameters, and fills in that dictionary according to the existing code in the __prepare__ method. Then, call that function in the beggining of a class body, passing in the dictionary returned by the locals() call as parameter. That is it: the class body namespace can be pre-filled in the sameway.
def prepare(bases, dct):
for base in bases:
dct["special_attribute"] = {}
if "special_attribute" in base.__dict__:
dct["special_attribute" ].update(base.__dict__["special_attribute"])
...
class MyClass(bytearray):
prepare((bytearray,), locals())
...
All that said, I really advise you to try if possible NOT to backport a project to Python2 at this point in time - it will just complicate your codebase - and give up using new features in a consistent way (for example, this tip above instead of __prepare__ )
Related
How do you set/get the values of attributes of t given by x?
class Test:
def __init__(self):
self.attr1 = 1
self.attr2 = 2
t = Test()
x = "attr1"
There are built-in functions called getattr and setattr
getattr(object, attrname)
setattr(object, attrname, value)
In this case
x = getattr(t, 'attr1')
setattr(t, 'attr1', 21)
If you want to keep the logic hidden inside the class, you may prefer to use a generalized getter method like so:
class Test:
def __init__(self):
self.attr1 = 1
self.attr2 = 2
def get(self,varname):
return getattr(self,varname)
t = Test()
x = "attr1"
print ("Attribute value of {0} is {1}".format(x, t.get(x)))
Outputs:
Attribute value of attr1 is 1
Another apporach that could hide it even better would be using the magic method __getattribute__, but I kept getting an endless loop which I was unable to resolve when trying to get retrieve the attribute value inside that method.
Also note that you can alternatively use vars(). In the above example, you could exchange getattr(self,varname) by return vars(self)[varname], but getattrmight be preferable according to the answer to What is the difference between vars and setattr?.
Note: This answer is very outdated. It applies to Python 2 using the new module that was deprecated in 2008.
There is python built in functions setattr and getattr. Which can used to set and get the attribute of an class.
A brief example:
>>> from new import classobj
>>> obj = classobj('Test', (object,), {'attr1': int, 'attr2': int}) # Just created a class
>>> setattr(obj, 'attr1', 10)
>>> setattr(obj, 'attr2', 20)
>>> getattr(obj, 'attr1')
10
>>> getattr(obj, 'attr2')
20
I have two classes that inherit from the same base class, and they have some common methods (in fact, properties). I will need to do this:
input: an int and an object from either class;
output: the result of one of the methods (determined by the int) of the corresponding class.
I think I can use a dictionary to do this, as the following code:
class ChangeInt(object):
def bar(self, i):
print(i)
class PlusOne(ChangeInt):
def bar(self, i):
print(i+1)
class PlusTwo(ChangeInt):
def bar(self, i):
print(i+2)
methods_dict = {0:ChangeInt.bar}
print(methods_dict[0](PlusOne(), 0))
print(methods_dict[0](PlusTwo(), 0))
I expect the output to be 1,2, but I actually get this:
0
None
0
None
I would like to know how these results are generated and what should I do to fix it up. Thanks in advance.
I totally mess up the format in the comment, so I'll paste it here.
thanks to Ryan Haining in Dynamic Method Call In Python 2.7 using strings of method names, I've found another way to do this:
class ChangeInt(object):
def bar(self, i):
print(i)
class PlusOne(ChangeInt):
def bar(self, i):
print(i+1)
class PlusTwo(ChangeInt):
def bar(self, i):
print(i+2)
methods_dict = {0:'bar'}
getattr(PlusOne(), methods_dict[0])(0)
getattr(PlusTwo(), methods_dict[0])(0)
This may not be the best way to do it, but it produces the expected result:
class ChangeInt(object):
def bar(self, i):
if not ('ChangeInt' in str(self.__class__)):
self.bar(i)
else:
print(i)
class PlusOne(ChangeInt):
def bar(self, i):
print(i+1)
class PlusTwo(ChangeInt):
def bar(self, i):
print(i+2)
methods_dict = {0:ChangeInt.bar}
methods_dict[0](ChangeInt(), 0)
methods_dict[0](PlusOne(), 0)
methods_dict[0](PlusTwo(), 0)
and prints:
0
1
2
The bar() function in the base class calls the method associated with given self instance or the base class implementation if it's an instance of base class itself (just print(i)). This is important, without it the code will be calling self.bar(i) infinitely if you invoke it on the base class (i.e. until it reaches max allowable recursion call number).
The check if not ('ChangeInt' in str(self.__class__)): is necessary since issubclass will return True for the parent class too,
issubclass(class, classinfo)
Return true if class is a subclass
(direct, indirect or virtual) of classinfo. A class is considered a
subclass of itself. classinfo may be a tuple of class objects, in
which case every entry in classinfo will be checked. In any other
case, a TypeError exception is raised.
And the point is to distinguish between the base/parent class and any subclasses.
Finally, since your function calls don't return anything explicitly, they actually return None. That None is what you are printing when enclosing the calls in an additional print,
print(methods_dict[0](PlusOne(), 0))
I removed the extra print so you only print the (assuming) intended content.
I have an enum like this
#enum.unique
class TransactionTypes(enum.IntEnum):
authorisation = 1
balance_adjustment = 2
chargeback = 3
auth_reversal = 4
Now i am assigning a variable with this enum like this
a = TransactionTypes
I want to check for the type of 'a' and do something if its an enum and something else, if its not an enum
I tried something like this
if type(a) == enum:
print "do enum related stuff"
else:
print "do something else"
The problem is it is not working fine.
Now i am assigning a variable with this enum like this
a = TransactionTypes
I hope you aren't, because what you just assigned to a is the entire enumeration, not one of its members (such as TransactionTypes.chargeback) If that is really what you wanted to do, then the correct test would be:
if issubclass(a, enum.Enum)
However, if you actually meant something like:
a = TransactionTypes.authorisation
then the test you need is:
# for any Enum member
if isinstance(a, Enum):
or
# for a TransactionTypes Enum
if isinstance(a, TransactionTypes):
reliable solution:
from enum import IntEnum
from collections import Iterable
def is_IntEnum(obj):
try:
return isinstance(obj, Iterable) and isinstance (next(iter(obj)), IntEnum)
except:
return False # Handle StopIteration, if obj has no elements
I thought I`ve got a ugly way. eg:
print(o.__class__.__class__)
Output:
<enum.EnumMeta>
as mentioned use isinstance method to check weather an instance is of enum.Enum type or not.
A small working code for demonstration of its usage:
import enum
class STATUS(enum.Enum):
FINISHED = enum.auto()
DELETED = enum.auto()
CANCELLED = enum.auto()
PENDING = enum.auto()
if __name__ == "__main__":
instance = STATUS.CANCELLED
if isinstance(instance, enum.Enum):
print('name : ', instance.name, ' value : ', instance.value)
else:
print(str(instance))
Output:
name : CANCELLED value : 3
There are already good answers here but in case of it might be useful for some people out there
I wanted to stretch the question a little further and created a simple example
to propose a humble solution to help caller function who does maybe little knowledge about Enum
solve problem of sending arguments to functions that take only Enum
as a parameter by proposing a converter just below the file that Enum was created.
from enum import Enum
from typing import Union
class Polygon(Enum):
triangle: 3
quadrilateral: 4
pentagon: 5
hexagon: 6
heptagon: 7
octagon: 8
nonagon: 9
decagon: 10
def display(polygon: Polygon):
print(f"{polygon.name} : {polygon.value} ")
def do_something_with_polygon(polygon: Polygon):
"""This one is not flexible cause it only accepts a Polygon Enum it does not convert"""
""" if parameter is really a Polygon Enum we are ready to do stuff or We get error """
display(polygon)
def do_something_with_polygon_more_flexible(maybe_polygon_maybe_not: Union[Polygon, int, str]):
""" it will be more convenient function by taking extra parameters and converting"""
if isinstance(maybe_polygon_maybe_not, Enum):
real_polygon = maybe_polygon_maybe_not
else:
real_polygon = get_enum_with_value(int(maybe_polygon_maybe_not), Polygon, Polygon.quadrilateral)
""" now we are ready to do stuff """
display(real_polygon)
def get_enum_with_value(key: int, enum_: any, default_value: Enum):
""" this function will convert int value to Enum that corresponds checking parameter key """
# create a dict with all values and name of Enum
dict_temp = {x.value: x for x in
enum_} # { 3 : Polygon.triangle , 4 :Polygon.quadrilateral , 5 : Polygon.pentagon , ... }
# if key exists for example 6 or '6' that comes to do_something_with_polygon_more_flexible
# returns Polygon.hexagon
enum_value = dict_temp.get(key, None)
# if key does not exist we get None
if not enum_value:
... # if key does not exist we return default value (Polygon.quadrilateral)
enum_value = default_value # Polygon.quadrilateral
return enum_value
How come the length Current_Stock.open can be greater than 0 if I just created the instance of the class?
def initialize_stock(row):
Current_Stock=Stock()
print len(Current_Stock.open)
do some stuff than return object
Loop that calls initializer
for row in xrange(1,sheet.nrows,25):
New_Stock= Stock() #create new instance of class
New_Stock= initialize_stock(row)
stocks.append(New_Stock) #add instance to stocks array
Stock class
class Stock:
name=''
date=[]
open=[]
high=[]
low=[]
close=[]
percent_change_price=[]
percent_change_volume= []
The reason is, that your attributes are not instance variables, but class attributes.
You declared them on class level -- and in Python this means, that they are class attributes by default.
Only variables that are created inside methods are instance variables and also they must be always used with "self." prefix, e.g.:
def __init__(self):
...
self.open = []
...
I have a repeating set of lengthy try/except1/except2/etc blocks in a series of class methods that only differ by the outside class method being called on an outside class instance. Below is a simplified version (there are actually 4 exceptions that I am handling and eight methods that only differ by the instance method being called):
class MyClass(object):
def __init__(self):
self.arg = 'foo'
def method1(self, arg1):
err = -1
y = None
try:
x = AnOutsideClass(self.arg) # Creates a class instance of an imported class
y = x.outsideclassmethod1(arg1) # Calls an instance method that returns another different class instance
except MyException1:
x.dosomething() # Needed to handle error
except MyException2:
err = 0
finally:
del x
return y, err
def method2(self, arg1, arg2, arg3):
err = -1
y = None
try:
x = AnOutsideClass(self.arg)
y = x.outsideclassmethod2(arg1, arg2, arg3) # This is the only thing changed
# A different method with different argument requirements
except MyException1:
x.dosomething()
except MyException2:
err = 0
finally:
del x
return y, err
def method3 ...
I have been trying various ways of condensing this code by trying to wrap the two statements in the try: portion of the code by using nested functions, decorators, etc, but seem to fail due to the fact that I am have trouble translating other examples of this due to: 1) am creating a class instance that needs to be used later in one of the except blocks and 2) am calling an instance method and 3) I need to return the result of the instance method.
Is there anyway of accomplishing this with partial from functools or descriptors or any other means? I have a clunky implementation currently with an extended if/elif block that picks the instance method based on an integer code that I use in a wrapper function, but am thinking there must be a more elegant way. I am relatively new to Python and am at a loss...
You could use a function factory (i.e., a function that returns a function).
def make_method(methname):
def method(self, *args):
err = -1
y = None
try:
x = AnOutsideClass(self.arg) # Creates a class instance of an imported class
y = getattr(x, methname)(*args) # Calls an instance method that returns another different class instance
except MyException1:
x.dosomething() # Needed to handle error
except MyException2:
err = 0
finally:
del x
return y, err
return method
class MyClass(object):
def __init__(self):
self.arg = 'foo'
method1 = make_method('outsideclassmethod1')
method2 = make_method('outsideclassmethod2')
The make_method is passed the outside method name as a string.
getattr is used (inside method) to get the actual method from x given the string methname.
getattr(x, 'foo') is equivalent to x.foo.
The * in def method(self, *args) tells Python that method can accept an arbitrary number of positional arguments.
Inside method, args is a tuple. The * in y = getattr(x, methname)(*args) tells Python to pass the elements in args as individual arguments to the method returned by getattr(x, methname). The * unpacking operator is explained in the docs, here, and also in this blog.