Python Inheritance: Why does the Folder class inherit from the File class - python-3.x

The below code is from a book I'm reading related to OOP in Python 3. Can someone help me understand the logic of the below? It seems counterintuitive that the Folder class inherits from the File class. For example, in the below, when a Folder is instantiated, it seems that a File is also instantiated with the same name but in reality you would not want this to happen. What am I missing?
class File:
def __init__(self, name):
self.name = name
class Folder(File):
def __init__(self, name):
super().__init__(name)
self.children = []
root = Folder("")
etc = Folder("etc")
root.children.append(etc)
etc.children.append(File("passwd"))
etc.children.append(File("groups"))
httpd = Folder("httpd")
etc.children.append(httpd)
httpd.children.append(File("http.conf"))
var = Folder("var")
root.children.append(var)
log = Folder("log")
var.children.append(log)
log.children.append(File("messages"))
log.children.append(File("kernel"))

Related

How Can I Dynamically Create Python Class Instances Using a List?

I am trying to understand how to dynamically create instances of a python class.
The simple example below shows how to create a class instance
class Person:
def __init__(self, name):
self.name = name
emmy = Person("Emmy")
niels = Person("Niels")
print(emmy.name)
print(niels.name)
If I want to iterate through a list to create class instances, how can I dynamically execute a command the same as
emmy = Person("Emmy")
I have tried to dynamically do it with something like eval or exec method so that I can iterate through a list and be able to call the class instance name using item name from list.
class Person:
def __init__(self, name):
self.name = name
people = ["Emmy","Niels"]
for item in people:
eval('item = Person(item)')
print(emmy.name)
print(niels.name)
Thanks in advance for any suggestions.
I found a solution creating a string variable to use as a command for the exec function.
class Person:
def __init__(self, name):
self.name = name
people = ["Emmy","Niels"]
for item in people:
a = str(item) + ' = Person("' + str(item) + '")'
exec(a)
print(Emmy.name)
print(Niels.name)

Bidirectional dependencies between classes causing issues

I have a class to represent a resource (for the sake of the example, let's say a folder), and a factory class to create those resources.
The issue is that, for clarity purposes, I wish to provide each folder with it's own factory, allowing it to generate it's sub-folders.
This currently looks like this :
folder.py
import FolderFactory
class Folder
def __init__(self):
self.file_factory = FolderFactory(self)
self.sub_folders = []
folder_factory.py
import File
class FolderFactory
def __init__(self, folder):
assert isinstance(folder, Folder)
self.folder = Folder(folder)
def create_sub_folder(name):
// Create Folder
self.folder.sub_folders.append(new_folder)
But obviously this generate a circular reference, which cause an error.
Is there an issue with my design, or is there a way to implement this cleanly ?
The end goal would be to be able to write something along the lines of
folder.folder_factory.create_folder("new")
Please note that the actual factory class I'm working with have a large amount of functions to generate different resources in the parent resource, which explains the need to separate the object definition and the management functions.
Thanks a lot for taking the time to read !
You could pass a self from the FolderFactory to the constructor of the folder, to be used as a reference to its 'parent'.
import FolderFactory
class Folder
def __init__(self, factory):
self.file_factory = FolderFactory(self)
self.folder_factory = factory
self.sub_folders = []
import File
class FolderFactory
def __init__(self, folder):
assert isinstance(folder, Folder)
self.folder = Folder(folder, self)
def create_sub_folder(name):
// Create Folder
self.folder.sub_folders.append(new_folder)

Python - access parent's class attribute from child's class method

i'm stuck at this poin in my code where i need a method of a child class to use an attribute of the parent's class.
Here are the classes:
class Parent:
def __init__(self, section):
self.section = section
class Child(Parent):
def __init__(self, section):
super().__init__(section)
self.name = self.get_name()
def get_name(self):
section = self.section
name = "somestring_" + section
return name
Now when executing the code below i get that Child does not have the section attribute:
child = Child('section')
print(child.name)
The expected output of the code should be: somestring_section.
I've tried calling the attribute directly with: section = super().section and doesn't work.
Also tried to call it like this: section = Parent.section and doesn't work.
Also tried to call it like this: section = super(Child).section and doesn't work.
Examples taken from this post here on stackoverflow: Accessing attribute from parent class inside child class
Where i've made the error?
Thanks in advance

How to use tkinter entry .get() fuction in another class

I'm struggling to get a variable entry getter from another class, i know i have to pass the instance of the class im getting the variable from, but how would i use the actual variable in the class i would like to use it in?
Here is the class:
class NewEmployee:
def __init__(self, master):
self.master = master
self.master.title("Jans Corp")
self.master.configure(background="lightgrey")
self.master.geometry("300x500")
self.FirstNameEntry = tk.Entry(self.master)
self.SurnameEntry = tk.Entry(self.master)
self.AgeEntry = tk.Entry(self.master)
self.PostcodeEntry = tk.Entry(self.master)
Here is where i'd like to use self.FirstNameEntry.get()
class Database(NewEmployee):
def __init__(self, master):
conn = sqlite3.connect(':memory:')
c = conn.cursor()
def addEmployees(self):
with conn:
c.execute("INSERT INTO Employees VALUES (:first, :last, :age)",
{'first':emp.first, 'last':emp.last, 'age':emp.age, }) <-----
Here you can see i have added the instance of the class im want to get the info from but do not know how to call "FirstNameEntry.get()" in the database class.
Would i have to use NewEmployee.FirstNameEntry() or would it be something else?
Here you can see i have added the instance of the class im want to get the info from...
That is not how classes work. Inheritance is a "is a" relationship. Your code is saying that your Database class "is a" NewEmployee, which is clearly not true. Databases are not employees.
The way to do this is to pass an instance of Employee to your addEmployee method. Roughly speaking, it looks like this:
emp = NewEmployee()
db = Database()
db.addEmployee(emp)
That means that you need to modify addEmployee to accept the employee to be added, and to call the get method of the widgets:
class Database():
...
def addEmployee(self, emp):
with conn:
c.execute(..., {'first':emp.FirstNameEntry.get(),...})
Note that it's rather unusual to have something like an Employee class that has widgets in it. Usually it just has data, and you would have a separate class to represent the GUI (ie: you have one GUI but many employees)
For example, your GUI class would be:
class EmployeeForm():
def __init__(self):
...
self.firstNameEntry = tk.Entry(...)
...
You would create one instance of this at the start of your program:
class TheApplication():
def __init__(self):
...
self.employeeForm = EmployeeForm()
...
You might then have an Employee class that looks something like this:
class Employee():
def __init__(self, first, last, etc):
self.first = first
self.last = last
self.etc = etc
Then, you might add a getEmployee method in your GUI class like this:
class EmployeeForm():
...
def getEmployee(self):
first = self.firstEntry.get()
last = self.lastEntry.get()
etc = self.etcEntry.get()
return Employee(first, last, etc)
Then, somewhere in your code -- maybe the "save" button on the form or application -- you would do something like this:
employee = self.employeeForm.getEmployee()
db.addEmployee(employee)
That's not another class ... that's a subclass. You would call it the same way you defined it: with self. Also, remember that with all subclasses, you have to call the parent __init__ from the subclass.
class Database(NewEmployee):
def __init__(self, master):
super().__init__(master) #call parent __init__
conn = sqlite3.connect(':memory:')
c = conn.cursor()
def addEmployees(self):
with conn:
c.execute("INSERT INTO Employees VALUES (:first, :last, :age)",
{'first':self.FirstNameEntry.get(), 'last':self.SurnameEntry.get(), 'age':self.AgeEntry.get(), })

Create os.DirEntry

Does anyone have a hack to create an os.DirEntry object other than listing the containing directory?
I want to use that for 2 purposes:
tests
API where container and contained are queried at the same time
Yes, os.DirEntry is a low-level class not intended to be instantiated. For tests and things, you can create a mock PseudoDirEntry class that mimics the things you want, for example (taken from another answer I wrote here):
class PseudoDirEntry:
def __init__(self, name, path, is_dir, stat):
self.name = name
self.path = path
self._is_dir = is_dir
self._stat = stat
def is_dir(self):
return self._is_dir
def stat(self):
return self._stat
Even easier:
class PseudoDirEntry:
def __init__(self, path):
import os, os.path
self.path = os.path.realpath(path)
self.name = os.path.basename(self.path)
self.is_dir = os.path.isdir(self.path)
self.stat = lambda: os.stat(self.path)
In Python 3.5 os.DirEntry is not yet exposed.
Details: https://bugs.python.org/issue27038
Python 3.6 exposes os.DirEntry type, but it cannot be instantiated.
On Python 3.5 a type() on a DirEntry object returns posix.DirEntry

Resources