Why is an indeterminate state of existence of a variable bad programming? - python

And more to the point, how do I avoid it?
See the link below for further reference; specifically the reply by paxdiablo.
How do I check if a variable exists?
As you probably guessed, I have a scenario where I've programmed a web page that has a variable whose existence is unknown at run time.
What is happening is, a user uploads information that can be in several different formats. To be more concrete, an address. For example, the street may have a directional (southwest, north), and the address may have a condo qualifier (unit#2F). These (or things/scenarios like them) will be assigned to and represented by different variables. As the data is manipulated in my code, I have conditionals
if street_dir_var:
#do something
Hence my question(s): why is this bad form, and whats a proper substitute?
PS - if it matters, I'm coding in Python

Conditionals are fine. The issue is if street_dir_var is not even defined, that line will throw a NameError. You can technically catch NameError, but that makes for messy unmaintainable code. It also suggests that you are putting data into your variable names, which is a bad code smell.
In general, a variable should be defined in any logical branch that tries to access it. If it "doesn't apply" for whatever reason, it should at very least be None. This serves as a fine default value for your variables, and often serves as a default for keyword arguments which need one.
To get more specific here:
These (or things/scenarios like them) will be assigned to and
represented by different variables.
Really bad code smell. All those variables represent data for a single address - you need to aggregate all those variables into a single variable, be it a class, a list, a dict, or a namedtuple.
class Address:
def __init__(self, **kwargs):
self.street = kwargs.get('street')
self.directional = kwargs.get('directional')
self.condo = kwargs.get('condo')
user_data = parse_data(some_data_source) # user_data looks like a dict
address = Address(**user_data)
One address, one container. address.condo might be None, but at least it's defined when I ask for it.

Related

How to call a python function when you don't need to assign result

Suppose you have a function Car.find_owner_from_plate_number(plate_number) that will raise an Exception if plate is unknown and return an Owner object if plate number exists.
Now, you do not need Owner information in your script, just to know if plate number exists (ie no exception raised)
owner = Car.find_owner_from_plate_number('ABC123')
_ = Car.find_owner_from_plate_number('ABC123')
Car.fund_owner_from_plate_number('ABC123')
With first, IDE will complain that owner is not used afterwards
Second is ok since _ is a global variable, but will assign memory in line with Owner's size
Third should also do the job, cherry on the cake without consuming memory if I'm correct.
What's the best way / more pythonic between 2nd and 3rd way? I ask because I often see 2nd way but I would be tempted to say 3rd is best.
As a rule, if you don't care about the returned value of a function, then don't assign it to anything, and it will vanish once you're done with it. This applies not only in python, but also in Java and other garbage-collected languages. In C/C++ you need to be more careful with memory management to make sure you're not leaving any memory leaks, but they do allow this behavior, and if you didn't explicitly use malloc() it's usually fine.
As for whether it's good design for find_owner_from_plate_number() to be built this way: it's okay but not great. The optimal design (more idiomatic in Java, in my experience, less so in python since exceptions are more integrated into control flow in general) would probably be
if plate is present, return an Owner
if plate is not present, return None (or the language's equivalent null value, if not writing python)
and save exception-throwing for actual error behavior that isn't expected to happen during normal use (invalid license plate format, could not connect to database, etc.). In general, try to avoid using thrown exceptions for control flow, if you can avoid it.
That said, I've seen both patterns in use at various points, and using exception behavior in this way isn't unheard of.
TLDR: If you do not need the return value, do not assign it at all. If you need some parts of the return value, assign the rest to _.
Python explicitly has an "expression statement" that solely exists to evaluate an expression and ignore its return value. Since this is the simplest way to ignore return values, it should be the preferred approach whenever applicable.
Car.find_owner('ABC123')
When the return value should be ignored only partially, an "assignment statement" is required to assign the parts of interest. In this case, the name _ is idiomatic to mean "unused" for the parts that must be assigned to something but are not of interest; it is often used as *_¹ to ignore arbitrary many items.
# we only want the owner and ignore the model
owner, _ = Car.find_owner_and_model('ABC123')
# ignore everything but the first item
owner, *_ = Car.find_owner_model_make_and_other_stuff('ABC123')
Note that _ is still a fully functional variable which keeps its assigned object alive until the end of the scope or deletion. This is not usually an issue when used in short-lived functions, but may require explicit cleanup when used for large objects at global scope.
¹ The * is commonly known as the "star" or "splat" operator. It denotes iterable packing/unpacking.

How to use %s to name a list

I'm trying to create a system on Python that allows me to create a list called (user)total, 'user' being the name of the user before total. However this is subjective as any account with any username could be made within my program.
I have tried to use
%stotal = [''] %user
however this comes up with a syntax error. How would I manage to do this?
You can't do that kind of meta-programming in python! (not with the syntax you posted)
But instead you can create a dictionary of lists indexed by the user name:
total = {}
total['username1'] = [''] #list for this username total
total['username2'] = ['']
etc.
It is possible. Hopefully seeing how will help to illustrate why, as Hyperboreus says, it's not a good idea.
If you do dir() in your interactive Python environment, you'll get a list of names that are available in your current scope. There will always be one called __builtins__, which exposes all of the functions and constants in the builtins module. These functions and constants are defined to be exactly the same ones that are available right from the start of your Python session in the global namespace, which you can take a look at with the builtin function globals().
In accordance with the Python data model, every Python object has an element named __dict__ that's a dictionary object whose keys are member names. If obj is the name of some Python object in the current scope, obj.__dict__["keyname"] will access the same member that you could get to more simply through obj.keyname.
So putting this together, you can set key/value pairs in __builtins__.__dict__ directly:
>>> __builtins__.__dict__["testvarname"] = "testval"
>>> print testvarname
testval
Whew! Getting pretty abstract pretty quick here. This might be useful for defining behavior based on user input or something else that you might not know until runtime... but you can probably see how you're working through a lot of complexity to get there and sort of circumventing the normal rules that Python sets out to try to help you keep your programs organized and easy to understand. xndrme's answer is likely to be the more straightforward way to solve the bigger problem you're facing.

How to bind a name with multiple objects or values in python

I saw in a book about language description that says
On the other hand, a name can be bound to no object (a dangling pointer),
one object (the usual case), or several objects (a parameter name in a
recursive function).
How can we bind a name to several objects? Isnt that what we call an array for example where all elements have the same name but with index? For a recursive function like the example here:
x = 0
def f(y):
global x
x += 1
if x < 4 :
y +=100
f(y)
else: return
f(100)
Is the name y binded with multiple values that are created recursively since the nametable has already the y name binded to an initial value which is being reproduced with recursion?
EDITED Just press here Visualizer and see what it generates. :)
No.
A name is bound to one single object . When we are talking about Python - it is either bound to a single object in a given context, or do not exist at all.
What happens, is that the inner workings may have the name defined in several "layers" - but your code will only see one of those.
If a name is a variable in a recursive function, you will only see whatver is bound to it in the current running context - each time there is a function call in Python, the execution frame, which is an object which holds several attributes of the running code, including a reference to the local variables, is frozen. On the called function, a new execuciton frame is created, and there, the variable names are bound again to whatever new values they have in the called context. Your code just "see" this instance.
Then, there is the issue of global variables and builtin objects in Python: if a name is not a local variable in the function execution context, it is searched in the globals variables for the module (again, just one of those will be visible).ANd if the name is not defiend in the globals, them, Python looks for it in globals().__builtins__ that is your last call.
If I understand you correctly, you're asking about what rules Python has for creating variables in different scopes. Python uses lexical scoping on the function level.
It's hard to tell exactly what you're getting at with the code you've written, but, while there may be a different value associated with y in different scopes (with a value of y defined at each level of recursion), your code will only ever be able to see one at a time (the value defined at the scope in which you're operating).
To really understand scoping rules in Python, I would have a look at PEP 227. Also, have a look at this Stack Overflow question.
Finally, to be able to speak intelligently about what a "name" is in Python, I suggest you read about how Python is a "Call-By-Object" language.
At this point, we are capable of understanding that, instead of a "nametable", python uses a dictionary to hold what is accessible in a given scope. See this answer for a little more detail. The implication of this is that you can never have two of the same name in a single scope (for the same reason you can't have two of the same key in a python dictionary). So, while y may exist in a dictionary for a different scope, you have no way of accessing it, since you can only access the variables in the current scope's dictionary.
The key is:
several objects (a parameter name in a recursive function).
The passage is almost certainly not referring to arrays, but simply to the fact that in a recursive function (or any function, but a recursive function is likely to have multiple activations at one time), a parameter may be bound to a different value in each recursive call.
This does not mean that you can access each such object in every stack frame; indeed the point of the technique is to ensure that only one such value is accessible in each stack frame.
Firstly, you should mention in the question that the sentence from the book is not related explicitly to Python (as jsbueno wrote, one name is bound to exactly one object in Python).
Anyway, name bound to no object is a bit inaccurate. Generally, names are related to variables, and name related to a dangling pointer is the name of that pointer variable.
When speaking about the variable scope (i.e. the part of code where the variable is used), one variable name can be used only for a single value at a time. However, there may be other parts of code, independent on the one where we think about that variable. In the other part of code, the same name can be used; however, the two variables with the same name are totally isolated. This is the case of local variables also in the case of function bodies. If the language allows recursion, it must be capable to create another isolated space of local variable even for another call of the same function.
In Python, each function can also access outer variables, but it is more usual to use the inner, local variables. Whenever you assign a name some value, it is created in the local space.

iterate a list when list name is dynamically generated

How do I iterate through a list whose name will be dynamically generated?
boneList_head =['def_neck', 'def_armbase']#hard coded list
itemType='head'# result of a user button press
...
def selectBones():
global itemType
bones =('boneList_'+itemType)# evaluates as a string , not name of a list
for bone in bones:
cmds.select(bone, tgl=True)
the problem is bones is getting evaluated as a string, when I need it to evalute as the name of a list.
Dynamically generating variable names is almost always a bad approach. Use a dictionary!
bonedict = {'boneList_head': ['def_neck', 'def_armbase']}
itemType='head'
def selectBones(itemType):
bones = bonedict['boneList_' + itemType]
for bone in bones:
cmds.select(bone, tgl=True)
Please ignore my previous answer (visible in my edit history) which was stupid -- boneheaded, even. But I blame its stupidity on dynamic variable name generation!
Let me elaborate on why dynamic variable name generation is a bad idea.
Because dynamic variable generation masks variable name definitions. It's hard to tell what has been defined and what hasn't, so it's easy to accidentally redefine a variable. This is a major source of potential bugs.
Because dynamic variable manipulation hides state changes under another layer of obfuscation. To some degree, this is true anytime you create a dictionary or a list. But one expects lists and dictionaries to demand a little extra thinking. Variable names, on the other hand, should be dead simple. When variable definitions and redefinitions require deep thought to understand, something is wrong.
Because dynamic variable generation pollutes the namespace. If you have so many variables that you have to automatically generate them, then they should live in their own namespace, not in the locals of a function, and definitely not in the global namespace. In his style guide for the linux kernel, Linus Torvalds advises that if a function has more than 5-10 local variables, you're doing something wrong.
Because dynamic variable generation contributes to high coupling, which is a bad thing. If you assign to values to a dictionary, you can pass that dictionary back and forth until the cows come home, and all anyone has to know about is that dictionary. If you dynamically create variable names in the global namespace of a module, then if another module wants to access those variable names, it has to know all about the way they were generated, what other variables in that module are defined, and so on. Also, passing the variables around becomes much more complex -- you have to pass around a reference to the module itself, probably using sys.modules or other questionable constructs.
Because dynamic variable generation is ugly. eval looks neat and clean, but it really isn't. It can do anything. Functions that can do anything are bad, because you can't tell at first glance what they're doing here. A well-defined function does one thing, and does it well; that way, whenever you see that function, you know exactly what's happening. When you see eval, literally anything could be happening. In this sense, eval is like goto. The problem with goto is not that you can't use it correctly; it's that for every possible correct use of goto, there are 500,000,000 terrifyingly wrong ways to use it. I won't even discuss the security problems here, because in the end, that's not the real problem with eval.
I agree with the other comments that your approach is probably not the best. But the following should work:
bones = eval('boneList_' + itemType)
This will run the python interpreter on "boneList_head", and return the list.
NOTE: As Adam Mihalcin mentioned in the comments, you should be very careful about only running eval on data that you trust or have validated. A malicious user could inject arbitrary code into the itemType variable to access the os, etc.
This is an ugly hack, but it works...(of course, you need to get the correct module)
import sys
boneList_head =['def_neck', 'def_armbase']
itemType='head'
...
def selectBones():
global itemType
bones=vars(sys.modules["__main__"])['boneList_'+itemType]
for bone in bones:
cmds.select(bone, tgl=True)
This really isn't different than what other people are saying however-- We're using vars to construct a dictionary to get the list you want -- why not just pass a dictionary (or the correct list) to the function selectBones in the first place?

Python: Using a dummy class to pass variable names?

This is a followup to function that returns a dict whose keys are the names of the input arguments, which I learned many things (paraphrased):
Python objects, on the whole, don't know their names.
No, this is not possible in general with *args. You'll have to use keyword arguments
When the number of arguments is fixed, you can do this with locals
Using globals(). This will only work if the values are unique in the module scope, so it's fragile
You're probably better off not doing this anyway and rethinking the problem.
The first point highlighting my fundamental misunderstanding of Python variables. The responses were very pedagogic and nearly instantaneous, clearly this is both a well-understood yet easily confused topic.
Since I'd like to learn how to do things proper, is it considered bad practice to create a dummy class to simply hold the variables with names attached to them?
class system: pass
S = system ()
S.T = 1.0
S.N = 20
S.L = 10
print vars(S)
This accomplishes my original intent, but I'm left wondering if there is something I'm not considering that can bite me later.
I do it as a homage to Javascript, where you don't have any distinction between dictionaries and instance variables. I think it's not necessarily an antipattern, also because differently from dictionaries, if you don't have the value it raises AttributeError instead of KeyError, and it is easier to spot typos of the name. As I said, not an antipattern, provided that
the scope of the class is restricted to a very specific usage
the routine or method you are calling (e.g. vars in your example) is private in nature. I would not want a public interface with that calling semantics, nor I want it as a returned entity
the name of the "dummy" class is extremely clear in its intent and the kind of aggregate it represents.
the lifetime of that object is short and uneventful. It is just a temporary bag of data.
If these constraints are not respected, go for a fully recognized class with properties.
you can do that, but why not use a dictionary?
but if you do that, you're better off passing keywords args to the class's constructor, and then let the constructor copy them to the app's members. something like:
class Foo(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)

Categories

Resources