0

Suppose a "person" class contains name, age and phone number.

When creating a person object, I would like to set phone number by looking up an external phone book rather than explicitly passing a phone number.

Option 1: Store phone book as a class variable

class person():

    phonebook = {}

    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.phone = self.phonebook[self.name]

person.phonebook = {'dan':1234}
dan = person('dan', 30)

Option 2: Create a class object without phone number then have a separate function to load it.

class person():

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def loadphone(self, phone):
        self.phone = phone

phonebook = {'dan':1234}
dan = person('dan',30)
dan.loadphone(phonebook['dan'])

Both solutions do not seem optimal. Option 1, every person carries a phone book (unnecessarily). Option 2 requires 2-step initialization.

Is there a better way to create a person object without 1) explicitly passing a phone number or phone book during initialization, 2) storing phone book as a class variable, and 3) requiring a multi-step initialization?

James Kang
  • 389
  • 1
  • 3
  • 8
  • 1
    Option 1 would have everyone carrying the same phonebook in python. – cssko Jul 20 '17 at 17:37
  • 3
    "Option 1, every person carries a phone book (unnecessarily)" This is not true, every instance has *access* to a single phone book which is stored as data on the class (and lookup on an instance will check the class dictionary if not found on the instance). – Jared Goguen Jul 20 '17 at 17:37
  • 1
    _"every person carries a phone book (unnecessarily)"_ - Incorrect. Every person has _accesses_ to the phone-book, but not every person carries a phone-book. The class object is what stores the phone-book. – Christian Dean Jul 20 '17 at 17:37
  • In option 1, there's no `self.phonebook`. – ForceBru Jul 20 '17 at 17:37
  • 1
    In option 1, the phonebook belongs *to the class*. The instances of a class have access to it's namespace, though. – juanpa.arrivillaga Jul 20 '17 at 17:37

3 Answers3

3

As discussed in this post, defining a variable outside of any methods in the class, while still being defined in a class makes it a static variable, such as the one you have:

class person():

    phonebook = {}

This means that there is a single phonebook which all instances of the class refer to

person.phonebook{'dave':1234, 'joey':5678}

dave = person('dave', 30)
joey = person('joey', 23)

There is still only the one universal phonebook that all instances refer to. The one thing to change in that code is that you should not define it as self.phonebook['dave'] so it should look like

class person():

    phonebook = {}

    def __init__(name, age):
        self.name = name
        self.age = age
        self.number = phonebook[name]
Christian Dean
  • 22,138
  • 7
  • 54
  • 87
Professor_Joykill
  • 919
  • 3
  • 8
  • 20
1

Are you wanting to optionally define a phone number for a Person? You could do something like below:

class Person():
    def __init__(self, name, age, phone=None):
        self.name = name
        self.age = age
        self.phone = phone

dan = Person('dan',30, phone=1234)
stan = Person('stan', 60)
cssko
  • 3,027
  • 1
  • 18
  • 21
0

Firstly, as for me, it's too wide question and very depend on task. In one case you can access to PhoneBook, in another - it's bad idea (e.g. PhoneBook load data from server and creating 1000 of Person will produce 1000 requests).

Secondary, their is next approach:

class BasicPerson():
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def ToString(self):
        return('some code')

class PersonWithPhone():
    def __init__(self, basicPerson, phone):
        self.basicPerson = basicPerson
        self.phone = phone

    def ToString(self):
        return('another code ' + self.basicPerson.ToString())

person = PersonWithPhone(BasicPerson('', ''), '11111')

It's just example and may seems useless, but in many situations you can extract some core actions (ToString, for example) and than wrote small decorators that expand each other.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
Green_Wizard
  • 795
  • 5
  • 11
  • Why not just make `PersonWithPhone` a child class and use the super method. – Professor_Joykill Jul 20 '17 at 18:16
  • Because you can easily pass some `PersonWithHomeAddress(WithMobile(WithTwitter()))` and than wrap it into `DBStoredPerson`. Inheritance are provide same result only in simple cases. – Green_Wizard Jul 20 '17 at 18:24