5

Pretty sure I know the answer to this question, but wanted to ask the python community about that.

I'm working on a python project where the current trend is to cut the variable name or the class name to pass it as parameters in other methods... Like :

myVar.__classname__[6:] 

or worst :

try :
    ...
except Error as err :
    myVar = err.message.split(':')[0]
    getattr(myInst, myVar)

etc... that said, we have to respect a really strict naming convention that will fit with all those horrible line of codes, but I was wondering if that was a common practice and that I was completely out of the line or if I was correct to say that this is just... awful.

It seems like a very bad idea to me, but as we have no choice...

Thanks for any response that would help me

Edit : This is the actual code in the try/except if you would like to have more details :

except ValueError as err:
    field_error = self.klass.__name__ + '_' + err.message.split(':')[0]
    getattr(self.ui, field_error).setText(err.message) 

Edit : So as some asked for more details :

In the example above, We wanna set an error message in a field when value entered by user is wrong.

self.klass represent an SQL Alchemy class, and the "Naming convention" says that every field should start with the SQL Alchemy class name in front of it, then an underscore, and then the field where we set the error message ( currently the same that the user entered wrong ).

This will "construct" ( Oh god... this feels so bad ) the name of the ui field that is wrong, then we'll get it with the getattr on the general ui.

This feels very wrong as it is based on a naming convention that might have billions of exceptions when we'll start to have more classes... Actually, I wouldn't mind fixing this, but the entire project is based on this naming convention. The first example is based on the fact that we have different ui files for our app, and these are indexed by a code ( like 7CDGR01 ). These are then completed by a class to add behaviour ( signal processing... etc ). If I keep the same example, the class is named : Screen7CDGR01. Therefore, to have the code of the screen, you get the end of the classname, from the 6th caracter... then send it to another method etc, etc...

Think you all got it, this is not what I voted for, I think this is just bad, I'm no expert in python, but I think that even if python allows us to do a lot, it should not be used like that.

Syrupsystem
  • 181
  • 1
  • 11
  • In your second example, what represents `myInst` and `myVar`. Are they linked in any way to err ? – ibi0tux Jun 26 '13 at 08:48
  • Actually.. Absolutely not linked in any way with the error except that the message will have a message with the name of myVar in it ( again, this cannot be always the case so... ) – Syrupsystem Jun 26 '13 at 08:51
  • Can you please copy/paste the full part of code where it is used ? – ibi0tux Jun 26 '13 at 08:53
  • 1
    Vote to put on hold as opinion based, but for the record, that seems woeful to me. – brice Jun 26 '13 at 09:03
  • @brice : I have the anwser why it's dangerous (using decorators). – lucasg Jun 26 '13 at 09:07
  • You could give a more complete example that illustrates what problem this approach is trying to solve, and ask for better solutions to that problem. – Janne Karila Jun 26 '13 at 09:27
  • @georges Still if you have it, I'ld be happy to have a proof of why this is just NOT a good practice... – Syrupsystem Jun 26 '13 at 09:28
  • @Syrupsystem : a decorator can override everything, from class name to attributes. More generally, it is hacky at best to self-reference variables. code : http://ideone.com/HrB6Ju – lucasg Jun 26 '13 at 09:38
  • @georgesl : good point. The `myVar.__classname__[6:]` is in my opinion worse since the splitting is based on length rather on a character. This implies that is the class name length is changed a little bit for any reason, the code won't work anymore ... – ibi0tux Jun 26 '13 at 09:48
  • Added some details... – Syrupsystem Jun 26 '13 at 10:05
  • `decorators` will be suitable for your needs. – Dmitry Zagorulkin Jun 26 '13 at 12:45
  • @Syrupsystem have you been able to track down the person/group who decided on this convention to find out why they did it? Would love to hear the rationale behind this. This is all quite bizarre, and as you put it, just awful. – robjohncox Jun 28 '13 at 08:38
  • Actually, we had a sort of MVC structure, Models were represented in SQl Alchemy, View was in PyQT and the Controller was simply mapping View to models, as it should be. Then, new employees arrived, as we're only in internship, they considered that this structure was "too complicated", and then decided that the "Naming convention" ( Again I'm not an expert, but naming convention are only for readability I think... no? ) will simplify it... – Syrupsystem Jun 28 '13 at 09:32

2 Answers2

3

It's dangerous to use introspection on variables/class names because, in Python, names aren't consistent : Python introspection: access function name and docstring inside function definition

#!/usr/local/bin/python2.7


class myInst(): 
  iitt = 15
  pass

class deco():
    def __init__(self, id, *args, **kws):
        self.__id = id
        self.iitt = 25
        self.__name__ = "another name"

@deco
class myInst2():
  iitt = 15
  pass


# Overriding class name
print "MyInst name :", myInst.__name__    #"myInst"
print "MyInst2 name :", myInst2.__name__  #"another name"


# Overriding attribute value
try:
  raise ValueError("iitt: Error!")
except ValueError as err:
  myVar = err.message.split(':')[0]
  l = getattr(myInst, myVar)
  print l                                 # 15

try:
  raise ValueError("iitt: Error!")
except ValueError as err :
  myVar = err.message.split(':')[0]
  l = getattr(myInst2, myVar)
  print l                                 # 25

#Duck Typing
myInst = myInst2
try:
  raise ValueError("iitt: Error!")
except ValueError as err :
  myVar = err.message.split(':')[0]
  l = getattr(myInst, myVar)
  print l                                 # 25
Community
  • 1
  • 1
lucasg
  • 10,734
  • 4
  • 35
  • 57
2

In addition to what was said about Decorators, it's important to know that this kind of code is very difficult to read.

Python is known for its readability, things like

err.message.split(':')[0]

are very hard to understand by anyone new in the project. A mere suggestion on what could be done:

Except ValueError as valueError:
    validationError = new ValidationError(valueError)
    componentSelector = validationError.getComponentSelector(self.getClassName())
    getattr(self.ui, componentSelector).setText(validationError.message)

That way all unreadable code is encapsulated inside of getComponentSelector() method. And this is only one of possible solutions.

If you want to know what's good and bad when programming in Python, take some time to read https://stackoverflow.com/questions/228181/zen-of-python .

Community
  • 1
  • 1
Mironor
  • 1,157
  • 10
  • 25