user3773048
user3773048

Reputation: 6239

Parameter list with variable types Python 3?

I'd like to know if I can have a parameter list with keywords given inside a string that I can pass into a function? Basically, the parameter list may or may not have keywords, so the parameter list would have variable 'types'. Here's an example of what I'm trying to do:

from bs4 import BeautifulSoup
import urllib.request as urlreq
import my_parameters    # can have variable values

# my_parameters.useful_token_concept = ["h1", "class_ = some_class"]
# I want to pass these above parameters into a function; "class_" is
# a keyword, but it's wrapped in a string => gives me problems

url = my_parameters.url
page = urlreq.urlope(url)
pageHtml = page.read()
page.close()

soup = BeautifulSoup(pageHtml)
# something like the following line works:
# params = soup.find("h1", class_ = "some_class")
params = soup.find(*my_parameters.useful_token_concept)
# params = soup.find(my_parameters.useful_token_concept[0],\
         # my_parameters.useful_token_concept[1])

# I don't know how long the list of attributes/parameter-list to
# BeautifulSoup's find() function will be, nor do I know what keywords,
# if any, will be passed into find(), as given by a user to my_parameters.

print(params) # should print the html the user wants to scrape.

Upvotes: 0

Views: 179

Answers (3)

martineau
martineau

Reputation: 123463

You could create a string representation of how all the arguments would be passed and use eval() to turn them into something you could actually use in a real function call:

my_parameters.useful_token_concept = ["h1", "class_ = some_class"]

def func_proxy(*args, **kwargs):
    " Just return all positional and keyword arguments. "
    return args, kwargs

calling_seq = ', '.join(my_parameters.useful_token_concept)
args, kwargs = eval('func_proxy({})'.format(calling_seq))
print('args:', args)     # -> args: (<Header1 object>,)
print('kwargs:', kwargs) # -> kwargs: {'class_': <class '__main__.some_class'>}

parms = soup.find(*args, **kwargs)

Upvotes: 1

Alex Martelli
Alex Martelli

Reputation: 881675

Why not just use a better representation? I.e, instead of

my_parameters.useful_token_concept = ["h1", "class_ = some_class"]

use

my_parameters.useful_token_concept = ["h1", {"class_": "some_class"}]

Since these values' representation is up to you, using a dict to represent keyword parameters is much simpler than encoding them into a string and then having to parse that string back!

Upvotes: 2

Burhan Khalid
Burhan Khalid

Reputation: 174624

You need to split your token list into a dictionary of keyword arguments, and a list of positional arguments.

kwargs = {}
args = []
for i in my_parameters.useful_token_concept:
    bits = i.split('=')
    if len(bits) > 1:
       kwargs[bits[0].strip()] = bits[1].strip()
    else:
       args.append(bits[0].strip())

params = soup.find(*args, **kwargs)

Upvotes: 1

Related Questions