Having trouble with the self parameter - python

I am working on a small project and I am not sure if the error I am getting is due to the IDLE I am using or something I am doing wrong.
I am using OOP in python running on the Wing IDLE. I have the latest version of the python shell running on a Windows 8 PC.
In my program I have a method that takes user input and using that input it creates the parameters required to create a shelf.
'def subject_creator(self):
subject_name = input("Enter the subject name:")
subject_file = subject_name + "file"
name = subject_name
return subject_name, subject_file, name'
Ideally the program would then use the three returned statements namely subject_name, subject_file, and name in opening the new shelf.
'def __init__(self, subject_name, subject_file, name ):
subject_name = shelve.open ("subject_file", "c")
self.name = name
print("The", self.name ,"note has been created")'
while True:
print ("""
1.Create new note
2.Add new term
3.Look up term
4.Exit/Quit
""")
ans= input("What would you like to do?: ")
if ans=="1":
subject_creator()
note = Notebook(subject_name, subject_file, name)
subject_name.sync()
However when I run the program and in my main menu I select choice 1 which runs the code above, I receive and error that states.
<module>
builtins.TypeError: subject_creator() missing 1 required positional argument: 'self'
This is somewhat puzzling as I include the self parameter when I wrote the code for subject creator as shown above. Other than this I have no other errors.
Any feedback would be greatly appreciated.

You are confusing "function" and "method".
In Python, a method is a function defined inside a class scope, and it will receive the object as its implicit first argument:
class Example:
def try_me(self):
print "hello."
You would use it like this:
x = Example()
x.try_me()
and try_me() will receive x as its first (here, ignored) argument. This is useful so that the method can access the object instance's attributes etc.
Contrast this with a regular function, i.e. one defined outside of a class:
def try_me_too():
print "hello."
which is simply invoked like
try_me_too()
Tangentially, your example code does not pick up the values returned by your subject_creator function:
> if ans=="1":
> subject_creator()
> note = Notebook(subject_name, subject_file, name)
The scope where this happens doesn't have variables named subject_name etc. You need to create them somehow.
if ans=="1":
ick, bar, poo = subject_creator()
note = Notebook(ick, bar, poo)
(I chose nonsense variable names mainly to emphasize that these are different from the variables defined, and only available, inside subject_creator.)
Just to complete this, here is a demonstration of how self is useful.
class Otherexample:
def __init__(self, greeting):
self.greeting = greeting
def try_me_also(self):
print self.greeting
use like this:
y = Otherexample("hello.")
y.try_me_also()
Here, the greeting is a property of the object we created; the __init__ method receives it as its argument, and stores it as an attribute of the instance. The try_me_also method uses self to fetch this attribute, and print it.

This line causes your error
subject_creator()
You should change
def subject_creator(self):
subject_name = input("Enter the subject name:")
subject_file = subject_name + "file"
name = subject_name
return subject_name, subject_file, name
to
def subject_creator():
subject_name = raw_input("Enter the subject name:")
subject_file = subject_name + "file"
name = subject_name
return subject_name, subject_file, name
You don't need a parameter in your function if you won't use it.
Also,if you are using python 2.x, consider using raw_input() and not input(). For more info, please read differences between input() and raw_input().

Related

Python + Selenium: how to automatically add test name and ids parameter or number to screenshot name?

I am learning how to write tests in Python + Selenium based on Page Object.
In general, the test code itself looks like this:
pytest.mark.parametrize("first_name", [double_first_name, empty_form, long_first_name],
ids=["double_first_name", "empty_form", "long_first_name"])
def test_reg_form_name(browser, first_name):
passport_reg_page = RegForm(browser)
passport_reg_page.go_to_site()
passport_reg_page.reg_page()
passport_reg_page.reg_first_name(first_name)
passport_reg_page.reg_button()
passport_reg_page = RegFormExpectations(browser)
passport_reg_page.reg_expect_name()
assert rt_passport_reg_page.reg_expect_name()
browser.save_screenshot('screenshots/test_reg_1.png')
How to write and call a function so that the name of the test + parameter ids is automatically added to the name of the screenshot, or at least the name of the test + the number of each parameter run? For example:
browser.save_screenshot(f'screenshots/{"test_reg_form_name"}+"_"+{"ids"}.png')
or
browser.save_screenshot(f'screenshots/{"test_reg_form_name"}+"_"+{"001,002,003..."}.png')
I've been proposed to try:
def test_name(self, request):
testname = request.node.name
return testname
but got notice "Method 'test_name' may be 'static'"
Also the next method helps to get def name but I see no sense to write its name for further getting it:
browser.save_screenshot(f'screenshots/{test_reg_page.__name__}_1.png')

how to inherit __init__ attributes from parent class to __init__ in the child class?

I'm trying to inherit the attributes from parent class:
class Human:
def __init__(self,name,date_of_birth,gender,nationality):
self.name = name
self.date_of_birth = date_of_birth
self.gender = gender
self.nationality = nationality
To the child class Student:
class Student(Human):
def __init__(self,university,std_id,first_year_of_registration,study_program):
super(Student,self).__init__(name,date_of_birth,gender,nationality)
self.university = university
self.std_id = std_id
self.first_year_of_registration = first_year_of_registration
self.study_program = study_program
def select(c):
pass
def drop(c):
pass
def __str__(self):
return 'Student ID {self.std_id},and student name is {self.name} and his study program is {self.study_program}'.format(self=self)
So i can create an object using both (parent,student) attributes like So:
s = Student('mark','2000-1-1','M','country','school',2017159,2017,'SE')
then i can:
print(s)
and invoke __str__ function like so:
Student ID 2017159,and student name is mark and his study program is SE
but whenever i create the object it give me error:
Traceback (most recent call last):
Python Shell, prompt 7, line 1
builtins.TypeError: __init__() takes 5 positional arguments but 9 were
given
i'm new to python. So i searched the internet and tried to do like some of the inheritance examples, like so:
Human.__init__()
but nothing worked, also i checked many answers here but none of them solved my problem.
hope anyone can help and point out what is wrong here.
def __init__(self,university,std_id,first_year_of_registration,study_program)
but
Student('mark','2000-1-1','M','country','school',2017159,2017,'SE')
?
Well, you see, Python is not a mind-reader. You need to tell it what you want.
Right now Python wants all and only university,std_id,first_year_of_registration,study_program, nothing more, nothing less.
This means, you need to tell it to get other elements:
class Student(Human):
def __init__(self,name,date_of_birth,gender,nationality, university,std_id,first_year_of_registration,study_program):
...
or by saying "and get some other elements". But remember! Those other elements must be at the end of the constructor!
class Student(Human):
def __init__(self,university,std_id,first_year_of_registration,study_program, *args, **kwargs):
super(Student,self).__init__(*args, **kwargs)
...
It basically catches all positional arguments (args) and keyword arguments (kwargs) and passes them further.
As I said, it only takes argument from the end, so you need to do:
Student('school',2017159,2017,'SE', 'mark','2000-1-1','M','country')
The way interpreter sees it, it will take 1st argument and put it in university, then 2nd in std_id... up to study_program, and then put the rest in the list args.

do i have to declare a variable twice when it is already declared in another def?

I am making a arithmetic quiz in python. At the start of the quiz it asks the user what class they would like to input results for, this is in the def classname(). Later on when the quiz is finished, the program will write the scores to a text file if the user does not want to repeat the quiz like this:
def classname():
class_name = input("Which class do you wish to input results for?")
# the rest of my code for my introduction
#
#
#
#
def askquestion():
# all of my code to ask the user the arithmetic question
#
#
#
# code to ask the user if they want to repeat the quiz
#if they dont want to repeat the quiz then this code is run
else:
filename = class_name + ".txt"
# code that will write the scores to a text file
When i run this code i get this error:
filename = class_name + ".txt"
NameError: name 'class_name' is not defined
Do I have to declare the variable "classname" again in askquestion() or is there a way python can recognise I have already declared the variable?
Unless you define your variable as global, you will have to redefine it, or pass the value in your code to subsequent functions as an argument.
You can pass in an argument to askquestion, as it currently stands, the variable class_name is out of scope for the function .
So, your function definition changes to
def askquestion(class_name):
...
...
And now, when you call the askquestion function, you will have to pass the class_name to it.
A working example will look something like below:
def classname():
class_name = input("Which class do you wish to input results for?")
...
...
return class_name
def askquestion(class_name):
...
else:
filename = class_name + ".txt"
# code that will write the scores to a text file
if __name__ == `__main__`:
class_name = classname()
askquestion(class_name)
Variables declared inside a function are local to that function and either need to be passed or returned to other methods or moved outside of the function to make it global, which needs to be explicitly declared when using it inside a function:
So you could return the class_name from classname() and use classname() in askquestion():
def classname():
class_name = input("Which class do you wish to input results for?")
return class_name
def askquestion():
...
else:
filename = classname() + ".txt"
# code that will write the scores to a text file
Your code declares the variable class_name inside the class_name() function, so it's not accessible outside. If you declare the variable class_name outside the class_name() function, it will be accessible to the askquestion() function.

AttributeError: 'module' object has no attribute 'newperson'

I am currently learning python programming (and am a beginner at it). Currently I am stuck on files exercises (so these are set things I need to do, rather than doing whatever I want. Unfortunately, it also means I probably can't do any complicated (for me) shortcuts)
Currently using Python 3.2.2
I need two different programs. One is to input what the user types in (a name and a DOB) and put that into records in a list and write that into a binary file. The other is to read that file and print that into a table using padding.
Codes:
First
import pickle
class newperson():
def __init__(self):
self.name = ""
self.dob = ""
stop = False
people = []
print("When you want to stop just hit enter")
count = 0
while stop == False:
name = input("Please Enter the name: ")
if len(name) == 0:
stop = True
else:
people.append(newperson())
people[count].name = name
people[count].dob = input("Please enter their DOB: ")
count = count + 1
file = open("ex9.4.dat", "wb")
pickle.dump(people,file)
file.close()
Second:
import pickle
myfile = open("ex9.4.dat", "rb")
people = pickle.load(myfile)
print("{0:<15}{1}".format("Name","DOB"))
for item in people:
print("{0:<15}{1}".format(item.name,item.dob))
The problem is that I am getting the following error when trying to run the 2nd program:
AttributeError: 'module' object has no attribute 'newperson'
on
people = pickle.load(myfile)
Unfortunately, when I have looked for answers on the other questions, either none of the solutions have worked, don't apply to me or mostly just went WAAAY over my head.
What am I doing wrong?
Thanks in advance for the help.
When pickle loads the file it tries to creates newperson instances, but newpersonis not defined in the second program. To solve that problem, you could create a new file newperson.py just containing the definition of the class `newperson.py``
# newperson.py
class newperson():
def __init__(self):
self.name = ""
self.dob = ""
In both programs, import the class after the import or pickle:
from newperson import newperson
Alternatively, you could use a dictionary instead of the newperson class.
I think to unpickle (i.e. pickle.load) you have to have to class newperson somewhere in namespace. try importing class newperson into the module where you run pickle.load.

Getting error message when trying to attach a class to an object

i have a little problem when i try to attach a class to an object in python. I have a textfile 'file', which is seperated into a list for each line. The program will read every line and print a name and a longname. Imagine that the textfile look like this:
"John '\n' John Travolta" (...)
Here's my bit of code:
class Name:
def __init__(self, name, longname):
self.name=name
self.longname=longname
def __str__(self):
s="Name:"+self.name
s+="\n Longname:"+self.longname
def func():
for line in file:
name=line[:1]
longname=line['\n':]
c=Name(name, longname)
c.func()
I get the error message that my 'name' and 'longname' is not defined but I did this with my function??? :(
It works if I put the function outside the class, like this:
def func():
for line in file:
name=line[:1]
longname=line['\n':]
c=Name(name, longname)
print c
Need help!
You need to assign something to name and longname before you can use them:
name = 'foo'
longname = 'foo bar'
c=Name(name, longname)
c.func()
but I did this with my function?
No.
Firstly, you didn't call your function yet. The function call is after the line that gives the error.
Secondly, the function has its own scope. The name there is different from the global name.
I don't think it makes any sense to move your func method inside the class definition. The code that you said works is a better way to do it.

Categories

Resources