Skip to main content
Question

How can I set an attribute to a list value within a PythonCaller?

  • February 18, 2022
  • 6 replies
  • 615 views

I am having issues setting an attribute within a python caller. 

I am reading in a list of strings, mutating the components in the list, then trying to overwrite the same list. Currently, the results of the output are the same as the input.

Below is an example of how I am doing it.

x = feature.getAttribute(list{}.item)
for i in len(x):
     <mutate items in list>
feature.setAttribute("list{}.item", x)

Can anyone let me know why this is not working, and how I can fix this? Thank you.

6 replies

hkingsbury
Celebrity
Forum|alt.badge.img+52
  • Celebrity
  • February 20, 2022
def processFeature(feature):
    x = feature.getAttribute('_list{}.item')
 
    for i in range(0,len(x)):
        _i = str(i)
        val = feature.getAttribute('_list{'+_i+'}.item')
        y = str(val)+'__'
        feature.setAttribute('_list{'+_i+'}.item',y)

 

The above will append '__' to the end of each item in the list.

 

A couple of things to note with your code, len(x) returns an int, ints aren't iterable, by placing it in range() we get a list which can be iterated over 

 

You need to indiviually update each item in the list using setAttribute()


  • Author
  • February 22, 2022
hkingsbury wrote:
def processFeature(feature):
    x = feature.getAttribute('_list{}.item')
 
    for i in range(0,len(x)):
        _i = str(i)
        val = feature.getAttribute('_list{'+_i+'}.item')
        y = str(val)+'__'
        feature.setAttribute('_list{'+_i+'}.item',y)

 

The above will append '__' to the end of each item in the list.

 

A couple of things to note with your code, len(x) returns an int, ints aren't iterable, by placing it in range() we get a list which can be iterated over 

 

You need to indiviually update each item in the list using setAttribute()

Sorry, the len(x) was an oversight in my example writing. 

Does this work if the output list is shorter than the current list? For example if I am using x.pop(_i) for some values, the items at the end of the list may be missed.


ebygomm
Influencer
Forum|alt.badge.img+32
  • Influencer
  • February 22, 2022

You can use this syntax to set the list, you don't necessarily need to iterate

feature.setAttribute("list{}.item", x)

But are you actually changing x in your code, before you use it to set the list attribute, e.g.

def processFeature(feature):
    x = feature.getAttribute('list{}.startIndex')
    x = [str(i)+"_test" for i in x]
    feature.setAttribute('list{}.startIndex', x)

 

 

 

 

 


hkingsbury
Celebrity
Forum|alt.badge.img+52
  • Celebrity
  • February 22, 2022
lukehicks wrote:

Sorry, the len(x) was an oversight in my example writing. 

Does this work if the output list is shorter than the current list? For example if I am using x.pop(_i) for some values, the items at the end of the list may be missed.

in that case you could do something like this (exclude when list val = 2).

if your input is ["1","2","3","4","5"], your output will be ["1__","3__","4__","5__"]

import fme
import fmeobjects    
 
def processFeature(feature):
    x = feature.getAttribute('_list{}.item')
    new = []
    
    for i in range(0,len(x)):
        _i = str(i)
        val = feature.getAttribute('_list{'+_i+'}.item')
        if val == 2:
            pass
        else:
            y = str(val)+'__'
            new.append(y)
 
    feature.setAttribute('_newList{}.item',new)

 


hkingsbury
Celebrity
Forum|alt.badge.img+52
  • Celebrity
  • February 22, 2022
ebygomm wrote:

You can use this syntax to set the list, you don't necessarily need to iterate

feature.setAttribute("list{}.item", x)

But are you actually changing x in your code, before you use it to set the list attribute, e.g.

def processFeature(feature):
    x = feature.getAttribute('list{}.startIndex')
    x = [str(i)+"_test" for i in x]
    feature.setAttribute('list{}.startIndex', x)

 

 

 

 

 

Yea, you can also iterate over the list natively, in this case it is better to do your (@ebygomm​ ) approach (went the range()/len() approach as @lukehicks​ initial code include the len() of the input list)


takashi
Supporter
  • February 23, 2022

For what it's worth, I prefer to use the enumerate function when iteration with for statement is required.

Example: Assign value of "_list{N}.item" to new attribute "_item_N"

        items = feature.getAttribute('_list{}.item')
        for i, v in enumerate(items):
            feature.setAttribute('_item_%d' % i, v)

 


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings