2

I have an excel file that contains some required parameters and their values and I am trying to feed them into the __init__ function of my class entity. I know the below must be setting self.key to each value in turn, but should I be "masking"(?) the .key?:

class Customer:
    def __init__(self):
        for key, value in zip(excelDF.attribs, excelDF.values):
            if key!=None and value !=None:
                self.key= value

To give an example of what I am trying for:

excelDF.attribs=['name','telephone']
excelDF.values=['Tom','01234-567890']
customer1=Customer()
print(customer1.name)
print(customer1.telephone)

gives...

Tom
01234-567890
Bendy
  • 3,506
  • 6
  • 40
  • 71
  • 1
    Use [`setattr()`](https://docs.python.org/2/library/functions.html#setattr) – Leon May 30 '17 at 10:50
  • 2
    @deepspace answer below is great, small remark for this code: don't use `=` and `!=` for singleton objects like `None`, use `is` if you need such check for some reason – Slam May 30 '17 at 10:54

3 Answers3

7

You should be using setattr:

class Customer:
    def __init__(self):
        for key, value in zip(excelDF.attribs, excelDF.values):
            if key is not None and value is not None:
                setattr(self, key, value)

If a key happens to be an invalid Python identifier it will only be accessible with getattr.

Usage example:

keys = ['a', 'b', 'c']
values = [1, 2, 3]

class Customer:
    def __init__(self):
        for key, value in zip(keys, values):
            if key is not None and value is not None:
                setattr(self, key, value)

cust = Customer()
print(cust.a, cust.b, cust.c)
# 1 2 3
DeepSpace
  • 78,697
  • 11
  • 109
  • 154
1

Another less conventional approach using type to define the class:

Customer = type("Customer",
                (),
                dict(zip(excelDF.attribs, excelDF.values)))

ref: http://python-course.eu/python3_classes_and_type.php

John 9631
  • 527
  • 5
  • 13
0

I want to present 2 alternatives:

#!/usr/bin/env python3


class Customer:
    def __init__(self, **kwargs):
        self.name = kwargs.get("name")
        self.number = kwargs.get("number")


class Customer2:
    name = ""
    number = ""

    @classmethod
    def from_dict(cls, d):
        o = cls()
        for k in [k for k in vars(cls) if not k.startswith("_")]:
            setattr(o, k, d.get(k))
        return o


keys = ["name", "number", "bla"]
values = ["John", "00109563221", "Blub"]

data = {k: v for k, v in zip(keys, values)}
c1 = Customer(**data)
c2 = Customer2.from_dict(data)

print(c1.name)
print(c2.number)

Here the stress lies on the constructor pulling in what it needs of the data instead of taking all that comes along.

Cave: Solution2 relies on the fact, that you only want dumb data objects, where the only fields you are interested in are defined class variables.

Thomas Junk
  • 5,588
  • 2
  • 30
  • 43