Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need to fix Line arguments to List instead of Tuple #45

Open
aoeftiger opened this issue Feb 21, 2020 · 3 comments
Open

Need to fix Line arguments to List instead of Tuple #45

aoeftiger opened this issue Feb 21, 2020 · 3 comments

Comments

@aoeftiger
Copy link

... otherwise Line.append_element does not work.

line = pysixtrack.elements.Line()

line.append_element(
    pysixtrack.elements.Multipole(knl=[0, 1e-2]), 
    'multipole')

... throws a

AttributeError                            Traceback (most recent call last)
<ipython-input-22-7a02c560d482> in <module>
      3 line.append_element(
      4     pysixtrack.elements.Multipole(knl=[0, 1e-2]),
----> 5     'multipole')
      6 line.append_element(
      7     pysixtrack.elements.DriftExact(length=1),

~/gsi/git/pysixtrack/pysixtrack/line.py in append_element(self, element, name)
     83 
     84     def append_element(self, element, name):
---> 85         self.elements.append(element)
     86         self.element_names.append(name)
     87         # assert len(self.elements) == len(self.element_names)

AttributeError: 'tuple' object has no attribute 'append'

... while initialising the kwargs elements and element_names with empty List instances instead of the default empty Tuple instances resolves the problem:

pysixtrack.elements.Line(elements=[], element_names=[])
@giadarol
Copy link

giadarol commented Feb 21, 2020

Hi Adrian,
the default values were originally lists, but this results in a the following unwanted behaviour:

class Test(object):
    def __init__(self, a=[]):
        self.a = a

t1 = Test()
t2 = Test()

print(t1.a, t2.a)
# gives: "[] []"

# I append something to the first object
t1.a.append(3)

print(t1.a, t2.a)
# gives: "[3] [3]!!!!"

In fact the .a members of the two objects point to the same list!!!

@aoeftiger
Copy link
Author

aoeftiger commented Feb 21, 2020

Ah I see.. Since the tuples also lead to unwanted behaviour, I propose a different approach to resolve both problems at once..

Instantiating the list at the time of Test definition leads to the same list for all Test instances. If instead we use None as default value and instantiate a list at the time of the __init__ call, your mentioned problem will be gone. This also fixes the above issue I have reported.

class Test(object):
    def __init__(self, a=None):
        if a is None:
            self.a = []
        else:
            self.a = a

t1 = Test()
t2 = Test()

print(t1.a, t2.a)
# gives: "[] []"

# I append something to the first object
t1.a.append(3)

print(t1.a, t2.a)
# gives: "[3] []"

@giadarol
Copy link

giadarol commented Feb 21, 2020

This would force us to write explicit constructors for the pysixtrack elements, which we wanted to avoid.

The tuple was a way of telling the user that he can rebind line.elements but not append to it.
Btw line is not the only case, the multipole behaves in the same way.

Probably the problem can be solved more elegantly modifying the baseclasses...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants