I am trying to do something like this:
class SomeEnum(str, Enum):
STRING_A = 'This is a string A with variable ' + variable
STRING_B = 'This is a string B with variable ' + variable
and use it like a template, for instance:
some_list.append(SomeEnum.STRING_A(variable))
is this even possible in Enums since it defies the purpose of Enums a bit? Or what else would you suggest instead of Enums? Thanks a lot!
I'd say define a __call__ method along with some string formatting
class SomeEnum(str, Enum):
STRING_A = 'This is a string A with variable %s %s '
STRING_B = 'This is a string B with variable %s %s'
def __call__(self, *args):
return self % args
print(SomeEnum.STRING_A("a", "b")) # This is a string A with variable a b
print(SomeEnum.STRING_B("c", "d")) # This is a string B with variable c d
The only rule : provide the same amount of paramater, as the string expects
Dynamic formatting
class SomeEnum(str, Enum):
STRING_A = 'This is a string A with variable '
STRING_B = 'This is a string B with variable '
def __call__(self, *args):
if len(args) == 1:
return self + args[0]
return self + ', '.join(args[:-1]) + " and " + args[-1]
print(SomeEnum.STRING_A("a")) # This is a string A with variable a
print(SomeEnum.STRING_B("a", "b")) # This is a string B with variable a and b
print(SomeEnum.STRING_B("a", "b", "c")) # This is a string B with variable a, b and c
No!. You can't do like that. It is not practical. The code you're writing cannot see intellisense. If you want to see it in public, then you can use self.
class SomeEnum:
def __init__(self, enum):
self.Enum = enum
self.STRING_A = f'This is a string A with variable {enum}'
self.STRING_B = f'This is a string B with variable {enum}'
num = 6
p1 = SomeEnum(num)
print(p1.STRING_A)
print(p1.STRING_B)
Related
So this is the class i'm testing:
class Test:
def find_string(self, string):
self.string = string
return string.find(string)
def add_string(self, string):
found = self.find_string('bar')
if found == -1:
string = string + ' bar'
return string
Here is my setup:
test_string = 'foo'
Test1 = Test()
new_string = Test1.add_string(string)
Results
Expected result: foo bar
Result: foo
If I replace the method call in add_string with the direct function find() it works fine. Please help me.
As for me all problem is that variables have similar names and this can be misleading.
Your string.find(string) means "bar".find("bar") but you expect "foo".find("bar")
You would have to use self.string = string in add_string() (instead of find_string()) and later in find_string() use self.string.find(string) instead of string.find(string) - and then you will have "foo" in self.string and "bar" in string so finally self.string.find(string) will mean "foo".find("bar")
class Test:
def find_string(self, string):
return self.string.find(string)
def add_string(self, string):
self.string = string
found = self.find_string('bar')
if found == -1:
string = string + ' bar'
return string
# --- main ---
test_string = 'foo'
test = Test() # PEP8: `lower_case_names` for variables
new_string = test.add_string(test_string)
print(new_string)
PEP 8 -- Style Guide for Python Code
I tried in all ways, could not get any solution for it.
I'm stuck in an application, i will give similar example ,
i have some strings,
arg = "school"
arg_2 = "college"
school = "enjoy"
college = "study"
i want to use it in code as below
if ( arg == arg )
\\ want to print content of school here,
else
\\ want to print content of college here,
can i make it with the help of string 'arg' only? i don't want to use the name of string 'school' here.
is there any method to do that?
You can use locals to do this
>>> arg = "school"
>>> arg_2 = "college"
>>> school = "enjoy"
>>> college = "study"
>>> locals()[arg]
'enjoy'
>>> locals()[arg_2]
'study'
So you could simply print a statement like
>>> "{} at {}".format(locals()[arg], arg)
'enjoy at school'
>>> "{} at {}".format(locals()[arg_2], arg_2)
'study at college'
PS: doing arg == arg is completely redundant, it will always evaluate to True
I am assuming that your goal is to get indirect access to values. In that case, consider putting your variables in a class or a dictionary. Here is an example of the class approach:
class mydata(object):
arg = "school"
arg_2 = "college"
school = "enjoy"
college = "study"
def value_of_value(self, s):
return getattr(self, getattr(self, s))
x = mydata()
print 'arg->', x.value_of_value('arg')
print 'arg_2->', x.value_of_value('arg_2')
This produces:
arg-> enjoy
arg_2-> study
I'm trying to learn how to correctly use classes in python, I'm fairly new to it but I cant get this class to return a string output of all the values. Ideally I'd like to be able to just str(packet) into a network socket.
class ARP():
dst_addr = ''
src_addr = ''
type = '\x08\x06'
payload = '\x00\x01\x08\x00\x06\x04\x00'
arptype = '\x01'
src_mac_addr = ''
src_ip_addr = ''
dst_mac_addr = ''
dst_ip_addr = ''
def __repr_(self):
return 'ARP'
def __str__(self):
return dst_addr + src_addr + type + payload + arptype \
+ src_mac_addr + src_ip_addr + dst_mac_addr + dst_ip_addr
p = ARP()
p.dst_addr = router_mac
p.src_addr = random_mac()
p.arptype = '\x02'
p.src_mac_addr = local_mac
p.src_ip_addr = ip_s2n(target_ip)
p.dst_mac_addr = router_mac
p.dst_ip_addr = ip_s2n(router_ip)
print 'PACKET: ', str(p)
return str(p)
This code outputs nothing at all. repr() outputs <__main__.ARP instance at 0x2844ea8> which I guess is what it's meant to do?
You are missing an underscore in your __repr__ method name:
def __repr_(self):
# ---------^
Python looks for __repr__, not __repr_.
Next, your __str__ method should refer to attributes on self, not to globals. Perhaps a str.join() call would be helpful here too:
def __str__(self):
return ''.join([getattr(self, attr) for attr in (
'dst_addr', 'src_addr', 'type', 'payload', 'arptype', 'src_mac_addr',
'src_ip_addr', 'dst_mac_addr', 'dst_ip_addr')])
This is a class which will take in as input and then output a polynomial in string form (both ways same format). Some arithmetic is performed in the various methods. I've been trying to inherit this class into another class that will then use the __mod__() special method of the first class (or make it's own special method if necessary but I don't see how you can't just use the original method) to perform the mod on intake. Seems like this goes into __init__() but I've tried 5 different versions of this, even going so far as to change the parent class, and I'm getting nowhere. I'm teaching myself Python so I'm sure that even a junior Python dev can see where I'm going totally wrong.
import re
class GF2Polynomial(object): #classes should generally inherit from object
def __init__(self, string):
'''__init__ is a standard special method used to initialize objects.
Here __init__ will initialize a gf2infix object based on a string.'''
self.string = string #basically the initial string (polynomial)
self.key,self.lst = self.parsePolyVariable(string) # key determines polynomial compatibility
self.bin = self.prepBinary(string) #main value used in operations
def id(self,lst):
"""returns modulus 2 (1,0,0,1,1,....) for input lists"""
return [int(lst[i])%2 for i in range(len(lst))]
def listToInt(self,lst):
"""converts list to integer for later use"""
result = self.id(lst)
return int(''.join(map(str,result)))
def parsePolyToListInput(self,poly):
"""
replaced by parsePolyVariable. still functional but not needed.
performs regex on raw string and converts to list
"""
c = [int(i.group(0)) for i in re.finditer(r'\d+', poly)]
return [1 if x in c else 0 for x in xrange(max(c), -1, -1)]
def parsePolyVariable(self,poly):
"""
performs regex on raw string, converts to list.
also determines key (main variable used) in each polynomial on intake
"""
c = [int(m.group(0)) for m in re.finditer(r'\d+', poly)] #re.finditer returns an iterator
letter = [str(m.group(0)) for m in re.finditer(r'[a-z]', poly)]
m = max(c); varmatch = True; key = letter[0]
for i in range(len(letter)):
if letter[i] != key: varmatch = False
else: varmatch = True
if varmatch == False: return "error: not all variables in %s are the same"%a
d = [1 if x in c else (1 if x==0 else (1 if x=='x' else 0)) for x in xrange(m, -1, -1)]
return key,d
def polyVariableCheck(self,other):
return self.key == other.key
def prepBinary(self,poly):
"""converts to base 2; bina,binb are binary values like 110100101100....."""
x = self.lst; a = self.listToInt(x)
return int(str(a),2)
def __mod__(self,other):
"""
__mod__ is the special method for overriding the % operator
returns remainder formatted as polynomial
"""
if self.polyVariableCheck(other) == False:
return "error: variables of %s and %s do not match"%(self.string,other.string)
if self.bin == other.bin: return 0
return GF2Polynomial(self.outFormat(self.bin%other.bin))
def __str__(self):
return self.string
def outFormat(self,raw):
"""process resulting values into polynomial format"""
raw = "{0:b}".format(raw); raw = str(raw[::-1]); g = [] #reverse binary string for enumeration
g = [i for i,c in enumerate(raw) if c == '1']
processed = "x**"+" + x**".join(map(str, g[::-1]))
proc1 = processed.replace("x**1","x"); proc2 = proc1.replace("x**0","1")
if len(g) == 0: return 0 #return 0 if list empty
return proc2 #returns result in gf(2) polynomial form
The desired result is to be able to call it on a new (child) class with the parent type and while changing the parent class as little as possible (if even at all). Note that class "BinaryField" is the intended child class:
p=GF2Polynomial("x**2+x**1+x**0")
a=BinaryField("x**1+x**0", p)
b=BinaryField("x**1", p)
On intake, the given polynomial should be modulus divided by the 2nd element (here it's 'p'). This is necessary for finite field math.
EDIT:
when running it with --
## "x**1 + x**0" polynomial string style input
poly1 = "x**14 + x**1 + x**0"; poly2 = "x**6 + x**2 + x**1"; poly3 = "y**6 + y**2 + y**1"
a = GF2Polynomial(poly1); b = GF2Polynomial(poly2); c = GF2Polynomial(poly3)
## "x+1" polynomial string style input
poly4 = "x**14 + x + 1"; poly5 = "x**6 + x**2 + x"; poly6 = "y**6 + y**2 + 1"
d = GF2Polynomial(poly4); e = GF2Polynomial(poly5); f = GF2Polynomial(poly6)
bf1 = BinaryField(poly1,b); print bf1
bf2 = BinaryField(poly4,e); print bf2
Both of these styles are possible because of the way I coded it, but they should both return the same answer. However the result on that code is:
>>>
x**5 + x**4 + x**3 + 1
x**5 + x
Also, when using BinaryField(poly4,d), which is just the same string with it's GF2Polynomial() initialization, this errors as:
AttributeError: 'int' object has no attribute 'string'
Does this solves your problem?
class BinaryField(GF2Polynomial):
def __init__(self, string, mod):
modded = GF2Polynomial(string) % mod
super(BinaryField, self).__init__(modded.string)
>>> p = GF2Polynomial("x**2+x**1+x**0")
>>> a = BinaryField("x**1+x**0", p)
>>> print a
x + 1
You can also make the BinaryField class to be just a factory method:
def BinaryField(string, mod):
return GF2Polynomial(string) % mod
Here is code, the class 'demo' defined by exec is not working when create a demo instance in _getTestObj().
FileName: test.py
class runOneIni():
def _getTestObj(self):
demo(self.tcName,secSetup,doc)
def start():
#implicit define 'demo' class by exec is not working, get error in runOneIni->_getTestObj, Error is :
# NameError: name 'demo' is not defined
a='global demo'
exec(a)
str="class demo(tInvokeMethod.tInvokeMethod): pass'
exec(str)
#Explict define demo class is working
#global demo
#class demo(tInvokeMethod.tInvokeMethod): pass
if __name__ == '__main__':
start()
(1) You have an unterminated string
(2) It is unnecessary to use exec to do this. class is itself an executable statement, which can appear anywhere any other statement can (except for a place where an expression statement is required).
You could do something like this:
class SomeBaseClass(object):
def __init__(self):
self.a = 1
self.b = 2
def make_new_class(name):
class TemplateClass(SomeBaseClass):
def __init__(self):
SomeBaseClass.__init__(self)
self.a = 3
return type(name, (TemplateClass,), {})
o1 = SomeBaseClass()
print o1.a, o1.b
NewClass = make_new_class('NewClass')
o2 = NewClass()
print o2.a, o2.b
Result:
1 2
3 2
The problem is not with defining a class via exec. The following works as intended:
exec 'class hi: pass'
Your problem is that "global" inside an exec statement has no effect outside it. According to the python documentation for exec:
the global is a directive to the parser. It applies only to code parsed at the same time as the global statement. In particular, a global statement contained in an exec statement does not affect the code block containing the exec statement, and code contained in an exec statement is unaffected by global statements in the code containing the exec statement.
Why are you doing that? (exec apart)
Why are you trying to do that with exec?
Also, doing it with exec will:
Not work.
Give different results in python-2.x and in python-3.x.
Example:
class demo:
a = 'a'
print(demo.a)
def start():
global demo
class demo: b = "b"
try:
print(demo.a)
except AttributeError:
print(demo.b)
if __name__ == '__main__':
start()
try:
print(demo.a)
except AttributeError:
print(demo.b)
That either in python-2.x and in python-3.x will give:
a
b
b
And now let's try it with exec:
class demo:
a = 'a'
print(demo.a)
def start():
exec('global demo', globals(), locals())
exec('class demo: b = "b"', globals(), locals())
try:
print(demo.a)
except AttributeError:
print(demo.b)
if __name__ == '__main__':
start()
try:
print(demo.a)
except AttributeError:
print(demo.b)
Output python2.7:
a
b
a
Output python3.2:
a
a
a
Q: How to 'dynamically create the class'?
As kindall already told you, exec is not the way to do that.
A metaclass or a class factory does that, but are you sure you actually need that?
I might be a little late to the party but I came up with something that seems to work okay. It will even correct type because of the setting property.
I'm sure this is all horribly unpythonic, but I think it's kinda fun.
def generateClass(propertyNames,propertyTypes):
string = 'class generatedClass(object):\n def __init__(self):\n'
for pN in propertyNames:
string += ' self._m' + pN + ' = None\n'
string += ' \n \n'
i = 0
for pN in propertyNames:
string += ' #property\n' \
' def ' + pN + '(self):\n' \
' return self._m' + pN + '\n' \
' #' + pN + '.setter' +'\n' \
' def ' + pN + '(self,a'+ pN + '):\n' \
' if a' + pN + ':\n'\
' self._m'+ pN + ' = ' + propertyTypes[i] + '(a' + pN + ')\n'\
' \n'
i += 1
exec(string)
return generatedClass()
if __name__ == '__main__':
c = generateClass(['SomePropertyName'],['str'])
print c.__dict__
setattr(c,'SomePropertyName','some string')
print c.__dict__
You need to add the global demoin the same exec string.
here the code with the result
class RunOneIni:
def _getTestObj(self):
self.tcName = 'tn'
print(demo(self.tcName, 'secSetup', 'doc').__class__.__name__)
def start():
t = 'class tInvokeMethod:\n\tclass tInvokeMethod:\n\t\tpass'
exec(t)
d = 'global demo\nclass demo(tInvokeMethod.tInvokeMethod):\n\tdef __init__(self, *args): pass'
exec(d)
demo()
if __name__ == '__main__':
start()
RunOneIni()._getTestObj()