1

I am trying to understand whether declaring variables inside constructors is an ok practice. I only need these variables inside the constructor. I am asking this because most of the times I've seen constructors they only contained self variables. I've tried to find an answer on the internet but had no luck.

Here is an example code

class Patient:
    def __init__(self, all_images_path: str):
        all_patient_images = os.listdir(all_images_path)
        all_patient_images = [(all_images_path + x) for x in all_patient_images if 'colourlay' in x]
        self.images: [Image] = [Image.open(img_path) for img_path in all_patient_images]

Is there anything wrong with the above code? If yes, what? Thank you!

2 Answers 2

2

__init__ is just a normal function that has a special purpose (initializing the newly created object).

You can do (almost) whatever you like in there. You typically see lines like self.name = arg because assignments like these are often required to set up the internal state of the object. It's perfectly fine to have local variables though, and if you find they make your code cleaner, use them.

Sign up to request clarification or add additional context in comments.

1 Comment

This is an important point. It is a perfectly ordinary function. It happens to get called automatically when an object is created, and the object instance will be passed as the first parameter (like all class methods), but beyond that it's just a function.
1

From a design standpoint, Patient.__init__ is doing too much. I would keep __init__ as simple as possible:

class Patient:
    def __init__(self, images: list[Image]):
        self.images = images

The caller of __init__ is responsible for producing that list of Image values. However, that doesn't mean your user is the one calling __init__. You can define a class method to handle the messy details of extracting images from a path, and calling __init__. (Note it gets less messy if you use the pathlib module.)

from pathlib import Path


class Patient:
    def __init__(self, images: list[Image]):
        self.images = images

    @classmethod
    def from_path(cls, all_images_path: Path):
        files = all_images_path.glob('*colourlay*')
        return cls([Image.open(f) for f in files])

Note that Image itself seems to take this approach: you aren't constructing an instance of Image directly, but using a class method to extract the image data from a file.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.