Python Forum
is it pythonic to add a name 'attribute' to an existing variable?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
is it pythonic to add a name 'attribute' to an existing variable?
#1
I have several variables in a list: - they are the result of ana analysis run using another library in python

vars = [run1, run2, run3, run4]
I now need to run one more analysis in a for loop and save the objects within the for loop. For this reason, during the save, i want to add a name attribute to the variables so that I can have a convenient filename for each.

Is it valid to do the following before the for loop in python? I know that attributes are set explicitly in classes, but for something minor like a string, is it valid to add a name attribute which is just a string descriptor to a variable?

vars[0].name = 'name1'
-- etc

thank you
Reply
#2
That would be totally valid for a class. Why not use a class?
Reply
#3
Can do it with namedtuple.
>>> from collections import namedtuple
>>> 
>>> lst = ['run1', 'run2', 'run3']
>>> name = namedtuple('Run', ['first', 'second', 'third'])
>>> name = name(*lst)
>>> name.first
'run1'
>>> name.third
'run3'
Reply
#4
A variable is just a name. Think of it as a key in a namespace dictionary. The only thing you can use a variable for is getting or setting the object associated with the variable name. Even if you could somehow attach a name to a variable, it would do you no good. Your list vars does not contain any variables. It contains objects. vars has no association with the variable run1. vars[0] and run1 just happen to reference the same object, and that can change at any time. Variables do not provide you with a way to do what you want.

You'll get an error if you try to set the "name" attribute of a string or a list. These classes prohibit you from adding attributes (likely something in the __setattr__()). You probably cannot do what you want by attaching the name to the object.

You could create a new object that includes the name and the object.
vars = [(var, f'name{i}) for i, var in enumerate(vars)]
Since it appears the filename is based on the array index, why not generate the names when you need them?
Reply
#5
Thank you, your explanation is very clear. I think it is my fault that I did not word my post correctly, apologies. Indeed the variable is attached to an object, I suppose the question should have been can I create an attribute to an object safely in python. To add a little more context, I have done this and it works however i do not know if this pythonic... the objects are then made in to a list so that I can iterate over them for another analysis and then save each one after each iteration, with the file name being the
object.name
that I have set as follows -

run1.name = 'run1'
run2.name .. etc

object_list = [run1, run2, run3]

for object in object_list:
    do_analysis(object)
    save_object(f'object_name_is_{object.name}.filetype')
the above works without issue, however, what i really want to know is, is it ok to do object.name = 'name' when I am not working with classes?

thank you

(Oct-04-2021, 08:24 PM)deanhystad Wrote: A variable is just a name. Think of it as a key in a namespace dictionary. The only thing you can use a variable for is getting or setting the object associated with the variable name. Even if you could somehow attach a name to a variable, it would do you no good. Your list vars does not contain any variables. It contains objects. vars has no association with the variable run1. vars[0] and run1 just happen to reference the same object, and that can change at any time. Variables do not provide you with a way to do what you want.

You'll get an error if you try to set the "name" attribute of a string or a list. These classes prohibit you from adding attributes (likely something in the __setattr__()). You probably cannot do what you want by attaching the name to the object.

You could create a new object that includes the name and the object.
vars = [(var, f'name{i}) for i, var in enumerate(vars)]
Since it appears the filename is based on the array index, why not generate the names when you need them?
Reply
#6
You obviously are working with classes, because this kind of thing only works for classes, oh, and everything in Python is an object and is associated with a class.

That you can do it means that the run1 object is an instance of a class that allows setting attributes. This is the default behavior for classes, but many of the built-in classes prohibit doing so. As I mentioned before, you cannot add attributes to list objects or string objects or many built in types because those classes contain code to forbid this.

The question here is not if it is Pythonic or not, because adding attributes to objects is about the most Pythonic thing you can do. The question is, "How much do you trust run1?" What is the class/type of run1? Do you have control over this type? How bad would it be for you if the authors of the code that created run1 decided they want run1 to be a closed class like list or string? How bad would it be for you if the authors of the class decided to add an attribute named "name"?

If I was you, and I had no control over the software that produces run1, I would only do things explicitly stated in the API for that software. I would not use variables that are not documented in the API, even if they are not "protected" using the _name convention. I would not use functions that are not documented in the API. I most certainly would not add my own attributes to objects. If you do those kinds of things you may find the next version of that software breaks your code. And if I decided to give into temptation and stuff a name into run1, I would give it a name that is much less generic than "name".
Reply
#7
(Oct-04-2021, 09:27 PM)deanhystad Wrote: You obviously are working with classes, because this kind of thing only works for classes, oh, and everything in Python is an object and is associated with a class.

That you can do it means that the run1 object is an instance of a class that allows setting attributes. This is the default behavior for classes, but many of the built-in classes prohibit doing so.

The question here is not if it is Pythonic or not, because adding attributes to objects is about the most Pythonic thing you can do. The question is, "How much do you trust run1?" What is the class/type of run1? Do you have control over this type? How bad would it be for you if the authors of the code that created run1 decided they want run1 to be a closed class like list or string? How bad would it be for you if the authors of the class decided to add an attribute named "name"?

If I was you, and I had no control over the software that produces run1, I would only do things explicitly stated in the API for that software. I would not use variables that are not documented in the API, even if they are not "protected" using the _name convention. I would not use functions that are not documented in the API. I most certainly would not add my own attributes to objects. If you do those kinds of things you may find the next version of that software breaks your code. And if I decided to give into temptation and stuff a name into run1, I would give it a name that is much less generic than "name".

thank you very much!! yes indeed they are all instances of a class but (as a learner), I wasn't sure that (as you say) not being explicitly in control of the class itself would or would not allow me to create attributes as user of this API, or the fact that i was able to was a weird quirk that worked for me, but was actually not really recommended - your answer clears up the confusion! and plenty to think about with future package updates and the potential for renaming and creating attributes on their end!

I shall avoid this practice :) thanks again.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Create new variable dependent on two existing variables JoeOpdenaker 6 2,933 Oct-25-2020, 02:15 PM
Last Post: jefsummers
  Assignment of non-existing class variable is accepted - Why? DrZ 6 4,187 Jul-13-2020, 03:53 PM
Last Post: deanhystad
  which is "better" (or more Pythonic)? Skaperen 2 2,017 Feb-01-2020, 03:10 PM
Last Post: Skaperen
  which is "better" (or more Pythonic)? Skaperen 7 3,141 Feb-01-2020, 03:51 AM
Last Post: Skaperen
  which is "better" (or more Pythonic)? Skaperen 8 3,222 Nov-16-2019, 06:46 PM
Last Post: Skaperen
  which is more Pythonic? Skaperen 5 2,779 Jul-16-2019, 01:00 AM
Last Post: Skaperen
  Function Attribute / Global Variable Confusion digitalmatic7 1 5,354 Feb-13-2018, 09:54 AM
Last Post: DeaD_EyE

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020