Python accessor and mutator methods - python

I am trying to solve a Python question that was described as follows:
Design a class that holds the following personal data: name, address,
age, and phone number. Write appropriate accessor and mutator methods.
Also, write a program that creates three instances of the class. One
instance should hold your information, and the other two should hold
your friends’ or family members’ information.
I am stumped on where to go from here. I think I have 90% correct but I am missing the main function code. My code is as follows:
class Person:
def __init__(self, name, address, age, phone):
self.__name = name
self.__address = address
self.__age = age
self.__phone_number = phone
#Set methods
def set_name(self,name):
self.__name = name
def set_address(self,address):
self.__address = address
def set_age(self,age):
self.__age = age
def set_phone(self,phone):
self.__phone = phone
#Get methods
def get_name(self):
reurn self.__name
def get_address(self):
reurn self.__address
def get_age(self):
reurn self.__age
def get_phone(self):
reurn self.__phone
def main():
#not sure what to put here?????
main()

You've created the blueprint for your objects. That's your Person class. Now it's time to build some Person's. You can do that with
p1 = Person("Your Name", "Address", 12, "phone_number")
p2 = etc
p3 = etc
You can access your getter and setter methods from your objects e.g.
p1.set_name("Joe")
print(p1.get_name()) # outputs "Joe"

Related

Python Inheritence from constructor

person.py
class Person:
"""---A class representing a person---"""
# Person constructor
def __init__(self,n,a):
self.full_name = n
self.age = a
class Student(Person):
# Student constructor
def __init__(self,n,a,s):
Person.__init__(self,n,a)
self.school = s
driver.py
from person import *
a = Student("Alice", 19, "Univ")
It throws TypeError: __init__() takes 3 positional arguments but 4 were given
I tried to change Student class to the following:
class Student(Person):
# Student constructor
def __init__(self,n,a,s):
super().__init__(n,a)
self.school = s
The error still exists.
Why does this happen? Is super() keyword required to add new attributes?
EDIT: The problem is solved. There was an indentation issue in the source code rendering this strange behavior, hence the question should be closed.
This line:
Person.__init__(self,n,a)
Is the problem. Recall that methods are automatically passed a reference to themselves, so you just passed a second one.
There's also a well-established pattern for this:
class Person
def __init__(self, name, age):
self.name = name
self.age = age
class Student(Person):
def __init__(self, school, *args):
super().__init__(*args)
self.school = school
student = Student('Washington Elementary', "Johnny Go'gettem", 10)
although note that simply removing your reference to self in the Person.__init__ call inside Student.__init__ would be sufficient.
Note that you can override the default method behavior with a couple of decorators that become quite useful in certain situations. Neither apply here, but just a bit of knowledge to tease your brain a bit:
def SomeClass:
attr = "class-scoped"
def __init__(self):
self.attr = "instance-scoped"
def some_method(self):
return self.attr == "instance-scoped"
#classmethod
def some_classmethod(cls):
return cls.attr == "class-scoped"
#staticmethod
def some_staticmethod():
return "I'm not given a \"self\" parameter at all!"
classmethods are particularly useful as alternate constructors
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
#classmethod
def from_tuple(cls, tup) -> "Person":
"""Expects a tuple of (name, age) and constructs a Person"""
name, age = tup
return cls(name, age)
#classmethod
def from_dict(cls, dct) -> "Person":
"""Expects a dictionary with keys "name" and "age" and constructs a Person"""
try:
name = dct['name']
age = dct['age']
except KeyError:
raise ValueError(f"Dictionary {dct} does not have required keys 'name' and 'age'")
else:
return cls(name, age)

Is there another way to get value from object method into object variable

I made code that goes like this
class Dog():
def breed():
return "rottwiller"
def __init__(self, name, age, breed=breed()):
self.name = name
self.age = age
self.breed = breed
Is there another way to achieve "self.breed" value instead of breed=breed(), but through function method as well.
for example something similar to this( I have tried out this that does not work):
def __init__(self, name, age):
self.name = name
self.age = age
self.breed = breed()
You shouldn't name an attribute and a method the same thing. That being said, my suspicions for why you are asking this question tell me I should point you towards the #property decorator.
class Dog():
def __init__(self, name, age, breed):
self.name = name
self.age = age
self._breed = breed
#property
def breed(self):
return self._breed
This is overkill for your example, but if you have a Dog class and a specific breed, I imagine you are thinking about subclasses and possibly more complicated things than you are doing here. Essentially, the #property decorator will allow you to access breed as an attribute, and will return the value of the call to the function you define under it by the same name.
There are a number of issues with the code posted.
The breed method is overwritten in __init__ method as you set the breed attribute. So the method should be renamed.
The breed method needs to specify the first argument self.
class Dog:
def get_breed(self):
return "rottwiller"
def __init__(self, name, age):
self.name = name
self.age = age
self.breed = self.get_breed()

Trying to create a object from a class by calling a function

I am working on a project that I need to create some objects dynamically from a class. I am not asking for anyone to solve it but just point me in the right direction. An example would be if I was working with Dogs.
class Dog(object):
"""Creating Dogs"""
def __init__(self, name, age, gender):
super(Dog, self).__init__()
self.name = name
self.name = age
self.name = gender
I would like however to have a function that I can pass this information into that would create a global object. The function would look like this:
def create_dog(name, age, gender):
name = Dog(name,age, gender)
return(name)
So theoretically if I passed the name "Jack" to the function I would have a object globally called "Jack" from the class. I am just trying to find a good way to do this if any. If this is completely against python I will figure out another way but I am sitting here stuck. I have also thought about nesting the class within my function but the namespace won't go into global.
you could create a global dictionary
dogs = {}
def create_dog(name, age, gender):
# maybe check if already exists
dogs[name] = Dog(name, age, gender)
With changing locals: (which is still bad, but not as much as changing globals)
def create_dog(name, age, gender, locals_=locals()):
dog = Dog(name, age, gender)
locals_[name] = dog
create_dog("jack", 3, "male")
print(jack)
Maybe you want to make an alternative constructor ?
class Dog(object):
"""Creating Dogs"""
def __init__(self, name, age, gender):
super(Dog, self).__init__()
self.name = name
self.name = age
self.name = gender
#classmethod
def create_dog(name, age, gender):
name = Dog(name,age, gender)
return name
See also discussion Meaning of #classmethod and #staticmethod for beginner?
A global dictionary is fine if you use a single file script, but for a more complex software you'll have to import all the 3 elements:
from dogs import dogs, create_dog, Dog
With class attribute you import just one name space. So you could do this:
class Dog(object):
"""Creating Dogs"""
members = []
def __init__(self, name, age, gender):
super(Dog, self).__init__()
self.name = name
self.name = age
self.name = gender
#classmethod
def create_dog(name, age, gender):
name = Dog(name,age, gender)
Dog.members.append(name)
return name
Now you can simply import Dog, and access the class attribute Dog.members

Add an object of one class to an object of another class in python

I have a class Participant as follows:
class Participant:
def __init__(self,name,level):
self.name = name
self.level =level
I also have another class Team as follows:
class Team:
def __init__(self,name):
self.name = name
I want to create a method in the class Team to add an instance of class Participant; for instance:
Assume myTeam is an empty, valid instance of Team.
Also assume myParticipant1 is a valid instances of Participant
myTeam.addParticipant(participant= myParticipant1)
AddParticipant method should add the instance myParticipant1 to the instance myTeam.
How do I acheive it in Python?
Aside from the inheritance questions we're talking about in the comments, this is pretty simple stuff.
class Participant(object):
def __init__(self, name, level):
self.name = name
self.level = level
class Team(object):
def __init__(self, name):
self.name = name
self.participants = []
def add_participant(p):
self.participants.append(p)
DEMO:
my_team = Team("Monty Python")
p_info = [("Adam", 10e5), ("Joe-bob", -1)]
participants = [Participant(name, level) for name, level in p_info]
for participant in participants:
my_team.add_participant(participant)
# say that 10 times fast....
In [1]: [p.name for p in my_team.participants]
Out[1]: ["Adam", "Joe-bob"]

how a class works

I am trying to figure out a really simple problem but still I can't quite get how a class works. For example, in case I wanted to create a class called "Friend" with an attribute called "name", does this mean I will have to give a variable called "name"before anything else ? Then how can i define the constructor to allow the specification of "name"? Is this code nonsense? Thanks in advance for any response
class Friend:
def __init__(self,name):
self.set_name(name)
def set_name(self,name):
self.name=name
def get_name(self):
return self.name
That code is not nonsense as in it accomplishes what you want to accomplish. It is not very pythonic, though. There are no reason you should use getter or setters. Just access the attributes directly. Like
class Friend:
def __init__(self,name):
self.name = name
you can instantiate your class by
friend = Friend('jeremy')
now just access name directly
print friend.name # jeremy
There is a good amount to learn about python classes luckily python provides excellent documentation for whatever version you are on.
in this example, to create a new friend you need to instantiate it with a name.
What you are referring to is default keyword arguments. The way you have specified it in your example means that name is required in the constructor. The way to make it default (and be able to be set after the constructor) would look like this:
class Friend(object):
def __init__(self,name=''):
self.name = name
def set_name(self,name):
self.name=name
def get_name(self):
return self.name
Now your class can be instantiated without a name:
aFriend = Friend()
As suggested in comments, it is not "considered pythonic" to have setters and getters for a basic attribute. But, if that attribute requires computation, then you can make it a property:
class Friend(object):
def __init__(self, firstname='', lastname=''):
self.firstname = firstname
self.lastname = lastname
#property
def firstname(self):
return self._first
#firstname.setter
def firstname(self, n):
self._first = n.capitalize()
#property
def lastname(self):
return self._last
#lastname.setter
def lastname(self, n):
self._last = n.capitalize()
#property
def fullname(self):
return "{0} {1}".format(self.firstname, self.lastname)
f = Friend('frank')
f.lastname = 'smith'
f.firstname
# 'Frank'
f.lastname
#'Smith'
f.fullname
#'Frank Smith'

Categories

Resources