Python Object Oriented Programming - python

I have to write a program to demonstrate a customer using their credit card to check out, I have spent a few hours trying to figure out how to do it and have provided my code below.
I have to make a class, then use it in a main function.
This is what I have so far:
class Customer:
def __init__(self, customer_name, credit_card_num, credit_security_code, debit_card_num, debit_pin):
self.customer_name = name
self.credit_card_num = credit_num
self.credit_security_code = credit_code
self.debit_card_num = debit_num
self.debit_pin = debit_pin
def inputCardInfo(self):
self.customer_name = str(input("Enter your name: "))
self.credit_card_num = str(input("Enter credit card Number: "))
self.credit_security_code = str(input("Enter 3-digit security code: "))
self.debit_card_num = str(input("Enter debit card number: "))
self.debit_pin = str(input("Enter 4-digit PIN: "))
then the main function:
from customer import Customer
def main():
print("Welcome to Wake-Mart. Please register.")
customer_name = input("enter name: ")
customer1 = Customer(customer_name)
print("Registration completed")
main()
I don't know the correct way to call the class methods. I feel if I can figure out how to make one of these work I can figure out the rest.

If you want to understand behaviors and properties more deeply I would recommend making a separate behavior for each value. (get_credit_num, get_debit_num, etc.)
Then, in your main, just call each function individually to get each value.
And to clarify, "class functions", or behaviors, are just things an object can do. You call them the same way you would any function, with the only difference being you put the name of the instance you are calling this behavior for before the function to replace "self". So if you were calling "InputCardInfo" for the object customer1, you would do it like so:
customer1.InputCardInfo(other parameters)

Your code as-is will not work because you are not passing all required parameters when initializing your class.
customer1 = Customer(customer_name)
All of the additional parameters besides self included in your def __init__(self, var1, var2, var3): needs to be passed to the class instance when initializing. There are also variable naming issues with your code but I hope my example below clarifies things for you.
A quick note first to help you better understand: self.customer_name = name does not make sense in your code because there is no parameter named name included in the __init__() method. You must associate an instance variable (self.whatever) to a known variable name passed in through the __init__(self, external_var) method so that self.whatever = external_var. Then, and only then, can you use class methods to call self.whatever and expect to receive the data you passed from external_var. Also, additional parameters you include after self in __init__(self, ..., ...) MUST be passed as variables when creating a class instance.
class Customer:
def __init__(self, customer_name, credit_card_num, credit_security_code, debit_card_num, debit_pin):
self.customer_name = customer_name
self.credit_card_num = credit_card_num
self.credit_security_code = credit_security_code
self.debit_card_num = debit_card_num
self.debit_pin = debit_pin
name = 'Mike'
cc_num = '0000 0000 0000 0000'
code = '111'
debit_num = '1111 1111 1111 1111'
pin = '1234'
new_customer = Customer(name, cc_num, code, debit_num, pin)

Related

[Python]: How to update python property in a good way

I'm new to Python and I'm working on a crawler project.
I have a case want to ask you about good way to handle.
For example.
class Student:
def __init__(
self,
user_id: str,
name: str = None,
age: int = None,
gender: str = None
):
self.name = name
self.age = age
self.gender = gender
user_id = "test_user_id"
# after crawling data by selenium/scrapy
# we have 2 types to build/update class property
# STYLE 1:
student = Student(user_id)
student.name = "AAAA"
student.age = "18"
student.gender = "male"
# STYLE 2:
name = "AAAA"
age = "18"
gender = "male"
student = Student(
user_id=user_id,
name=name,
age=age,
gender=gender)
About the #STYLE 1, I'm not really it's a good way or not. But about #STYLE 2 I think it's gonna have some problem because we have to define a lot of variables (hard to debug), and we have to guarantee the variables have to be initialized before create class instance.
That's my question, please give me your guys idea about this or which way do you guy prefer.
I'm afraid this question will be closed soon as it requires opinion based answers, and is probably out of scope here. Nevertheless it raises an interesting point, so I will give my two cents.
If you are talking about properties that you will set at once, on creation or immediately after, I would definitely go with the second approach. As Punit said in a comment, you can (and usually will) directly pass the values, without creating intermediate variables unless they are already there. And if some of the properties are really necessary to work with the instance, I would avoid specifying a default value, thus making them required.
This way the instance creation is IMO both more readable and more reliable. And if you have really many arguments, you can require that most or all are passed as kwargs, which will further improve readability.
Then you may sometimes have other properties which are not needed, or may be even unknown, at creation time - and of course those will be set later, with the first style.
The best to go about this is to have all this code compressed into a smaller block. This helps make the code look more concise. Also, you forgot to set user_id in STYLE #1.
class Student:
def __init__(self, id: int, name: str, age: int, gender: str):
self.id = id
self.name = name
self.age = age
self.gender = gender
data = [] #scraped data from target site
# assuming a user instance looks like this: { name, age, id, gender }
# using list comprehensions to make it look cool
# you can replace the arguments in `Student()` with whatever fits the
# response from target site
users = [Student(i.id, i.name, i.age, i.gender) for i in data]
Hope this helps!
I would distinguish 2 cases here: Creation of the instance and update.
In the first case you can directly assign the values to the constructor of the class.
classStudent:
def __init__(self, user_id: str, name: str = None, age: int = None, gender: str = None):
self.user_id = user_id # You forgot this attribute!
self.name = name
self.age = age
self.gender = gender
student = Student(
# All the values you have available like you do in STYLE 2
)
In the case of updating it would be easier without using the variables and assigning them directly. Hard to debug, as you said.
student.name = "YYYY"
student.age = "18"
student.gender = "male"
There is nothing wrong in doing this in Python as you don't have to make getters and setters like other languages.
Even so, it would be recommended that you add conditionals to check if the values are valid before making the modification.

Classes, self, input variables in self and self default values

I wrote variables in init's brackets, which should be default if I don’t enter anything, but I get an error if I don’t enter anything and python don’t see the default values ​​​​for the variables. I am using there input to understand the user what to enter and I would like to leave it.
class News:
def __init__(self, content='Test NEWS name', city='None', news_date_and_time='Not defined'):
self.content = str(input('Write down news content:'))
self.city = str(input('Write down news CITY:'))
self.news_date_and_time = datetime.now().strftime("%d/%m/%Y %H:%M")
pub = News()
I can achieve the input by passing it to the function, as I wrote below, but I want the function use an input and default values ​​which are written
class News:
def __init__(self, content='Test NEWS name', city='None', news_date_and_time='Not defined'):
self.content = content
self.city = city
self.news_date_and_time = datetime.now().strftime("%d/%m/%Y %H:%M")
pub = News('dog ate potatoes','New York')
pub = News(str(input('Input the content:')), str(input('Input the city:')))
How can I implement in the function an input of the variables and the default values ​​are which are written in the function if the wasn't written anything?
but I want the function use an input and default values ​​which are written
This violates the Single Responsibility Principle. Typically we design classes to take arguments similar to how you show in the second code example. This allows the flexibility of reuse because the class doesn't care where the value comes from. In your current situation, you get the values from user input, but you can easily create News objects from database values instead, for example.
To implement default values, I suggest building a separate class or function that decides whether to get input or to use default values. This will make your code in line with the Seperation of Concerns principle.
This function will work the way you want it to work if you test the value of input() and assign the parameter if it's empty:
class News:
def __init__(self, content='Test NEWS name', city='None', news_date_and_time='Not defined'):
self.content = input('Write down news content:') or content
self.city = input('Write down news CITY:') or city
self.news_date_and_time = datetime.now().strftime("%d/%m/%Y %H:%M")
As noted, though, this is bad design, because now it's impossible to create a News object without having it stop your script to ask for input. You should instead do this outside of the constructor:
class News:
def __init__(self, content, city):
self.content = content
self.city = city
self.news_date_and_time = datetime.now().strftime("%d/%m/%Y %H:%M")
pub1 = News("Dog ate potatoes", "New York")
pub2 = News(input("Enter content: "), input("Enter city: "))
Note that there's no reason to have a news_date_and_time parameter since you always use datetime.now in your constructor.

Calling a function from outside class with user input without using global

I am trying to avoid using global, instead I created a class. I am having trouble calling the class, instead, I am getting the following error
TypeError: phone.__init__() missing 1 required positional argument: 'NUMBER_INPUT'
Any ideas? Thanks in advance!
class phone:
def __init__(self,NUMBER_INPUT):
self.NUMBER_INPUT = NUMBER_INPUT
def phone_number(self):
"""validate user input of phone number"""
while True:
self.NUMBER_INPUT = input("Please enter your phone number: ")
if re.fullmatch(r"\d{3}-\d{3}-\d{4}" ,self.NUMBER_INPUT):
print("You phone number is: " + self.NUMBER_INPUT)
break
print("Please enter a valid phone number ex. 123-456-5678")
phone().phone_number()
So, I think you neither did read documentation nor watched/read any tutorial about Python classes. So I will explain it here for you.
Class is a "object project". It may have predefined methods, predefined values. It also may have a way to construct these dynamically.
Class object at first need to be instantiated and then initiated. That means that firstly you need to create an instance of a class, then to initiate default values.
Python has 2 methods for this.
__new__() creates a new instance of a class and returns it. It's already realised for every Python class, but there may be special cases for you to override it.
__init__(*args, **kwargs) initiates values of a class. You must define non-static values here or globally in class.
So, creating a class object is achieved in python by calling class like this
A_instance = A(*args, **kwargs)
That in words means create me instance of A with these args and kwargs
So in your code, you are using (actualy overriding) __init__(*args, **kwargs) with args = (NUMBER_INPUT,) and kwargs = None.
Thus you must provide NUMBER_INPUT every time you create an object of phone, like so:
phone1 = phone("123-456-7890")
phone2 = phone("098-765-4321")
You must provide a value for NUMBER_INPUT when calling phone() like phone("123").phone_number().
But it would be better if you will use dummy value for NUMBER_INPUT in constructor like:
class phone:
def __init__(self):
self.NUMBER_INPUT = ""
def phone_number(self):
"""validate user input of phone number"""
while True:
self.NUMBER_INPUT = input("Please enter your phone number: ")
if re.fullmatch(r"\d{3}-\d{3}-\d{4}" ,self.NUMBER_INPUT):
print("You phone number is: " + self.NUMBER_INPUT)
break
print("Please enter a valid phone number ex. 123-456-5678")
phone().phone_number()

How to use a method object (which is in the class) outside the class?

I have a method object with assigned value from user's input inside a class. The problem is i can't use the method object maxcount_inventory = int(input("How many Inventories: ")) outside the class. The error says "method' object cannot be interpreted as an integer"
class CLASS_INVENTORY:
maxcount_inventory = int(input("How many Inventories: "))
inventory_name = []
def __init__(Function_Inventory):
for count_inventory in range(Function_Inventory.maxcount_inventory):
add_inventory = str(input("Enter Inventory #%d: " % (count_inventory+1)))
Function_Inventory.inventory_name.append(add_inventory)
def Return_Inventory(Function_Inventory):
return Function_Inventory.inventory_name
def Return_Maxcount(Function_Inventory):
return maxcount_inventory
maxcount_inventory = CLASS_INVENTORY().Return_Maxcount
Another extra question if I may, how can i access items in the list per index outside the class? I have the code below, but I think it's not working. Haven't found out yet due to my error above.
for count_inventory in range(maxcount_inventory):
class_inv = CLASS_INVENTORY().Return_Inventory[count_inventory]
print(class_inv)
skip()
Here is my full code: https://pastebin.com/crnayXYy
Here you go I've refactored your code.
As #Daniel Roseman mentioned you should be using self rather than Function_Inventory, so I changed that. I also changed the return value of Return_Maxcount to provide a list as you requested.
class CLASS_INVENTORY:
maxcount_inventory = int(input("How many Inventories: "))
inventory_name = []
def __init__(self):
for count_inventory in range(self.maxcount_inventory):
add_inventory = str(input("Enter Inventory #%d: " % (count_inventory+1)))
self.inventory_name.append(add_inventory)
def Return_Inventory(self):
for item in self.inventory_name:
print(item)
def Return_Maxcount(self):
return self.inventory_name
maxcount_inventory = CLASS_INVENTORY()
inventory_list = maxcount_inventory.Return_Maxcount()
maxcount_inventory.Return_Inventory()
You can change the print statement at the bottom and set that equal to a variable to access it outside of the class itself.
In your code just change this:
maxcount_inventory = CLASS_INVENTORY().Return_Maxcount
to this:
maxcount_inventory = CLASS_INVENTORY().Return_Maxcount()
also change the variables in your class to have the self. prefix before them
like self.maxcount_inventory
the reason is you want to call your method , otherwise it will try getting a variable not the method.
you also want to change all your arguments in your functions inside of the class to self

i am creating two classes student(base) and detail.Why wont studen will access the variables roll_No ,class.?

![enter image description here][1]i am creating two classes student(base) and detail .Detail is inheriting all the attributes of base .I am initializing the attributes (roll_no,name and class_stud)subclasses of base with students object of subclass created with student.subclasses().Here is the code:
student=type('student',(object,),{})
def getinfo():
for studen in student.__subclasses__():
studen.roll_no=input("enter the roll number")
studen.name=input("enter the name of student")
studen.class_stud=input("enter the class")
def printinfo():
print('roll number ',roll_no,name,class_stud)
detail=type('detail',(student),{'info':getinfo(),'print':printinfo()})
ob=detail()
ob.info
ob.print
I have never seen anyone create Python classes this way, except to see if they could. You have quite a few errors, but this might do what you want (although that is not clear):
student=type('student',(object,),{})
def getinfo(self):
for studen in student.__subclasses__():
studen.roll_no=input("enter the roll number: ")
studen.name=input("enter the name of student: ")
studen.class_stud=input("enter the class: ")
def printinfo(self):
print('roll number ',self.roll_no,self.name,self.class_stud)
detail=type('detail',(student,),{'info':getinfo,'print':printinfo})
ob=detail()
ob.info()
ob.print()
As you can see, your main error was in not passing the object into the methods. Other errors included a missing comma after student when defining detail. See also comments by #abarnert.
This is a horrible way of defining a class in Python.
EDIT:
I have no idea why you are iterating over subclasses, this is probably what you meant for getinfo:
def getinfo(self):
self.roll_no=input("enter the roll number: ")
self.name=input("enter the name of student: ")
self.class_stud=input("enter the class: ")

Categories

Resources