1
\$\begingroup\$

I'm making a program that can add 2 terms that the user types.

I think I've got identifying or evaluating the terms down. I used classes because I just recently learned it and I also heard it was good practice in order to make your programs shorter. But, when it comes to adding 2 terms together (which is the code under the else and elif statements) I tried using classes but I have no idea how that would work, so I just sort of brute forced it. Is there a shorter or otherwise better way to code the adding part? Surely there is, and I would appreciate it if someone could show me what to learn or focus on or pretty much just any good advice so that I can code it cleaner.

class TermEva:
    def __init__(self, Variable, Coefficient):
        self.Variable = Variable
        self.Coefficient = Coefficient
        self.ExVariable = Variable
        if self.Coefficient < 0:
            self.ExVariable = "-" + self.Variable

    def SimTerm(self):
        return "{}{}".format(self.Coefficient, self.Variable)

    def Expanded_Form(self):
        ExpandedForm = []
        for n in range(abs(self.Coefficient)):
            ExpandedForm.append(self.ExVariable)
        return ExpandedForm

Term1 = TermEva(input("Enter Variable 1: "), int(input("Enter its Coefficient: ")))
Term2 = TermEva(input("Enter Variable 2: "), int(input("Enter it's Coefficient: ")))

print(Term1.SimTerm())
print(Term2.SimTerm())

if Term1.Variable == Term2.Variable:
    VariableSum = Term1.Variable
    CoefficientSum = Term1.Coefficient + Term2.Coefficient
    ExVariableSum = VariableSum
    if CoefficientSum < 0:
        ExVariableSum =  "-" + VariableSum

    ExpandedFormSum = []
    for num in range(abs(CoefficientSum)):
        ExpandedFormSum.append(ExVariableSum)
    TermSum = str(CoefficientSum) + str(VariableSum)
elif Term1.Variable != Term2.Variable:
    ExTerm1_Variable = Term1.Variable
    ExTerm2_Variable = Term2.Variable
    if Term1.Coefficient < 0:
        ExTerm1_Variable = "-" + Term1.Variable
    if Term2.Coefficient < 0:
        ExTerm2_Variable = "-" + Term2.Variable
    ExpandedFormSum = []
    for num in range(abs(Term1.Coefficient)):
        ExpandedFormSum.append(ExTerm1_Variable)
    for num in range(abs(Term2.Coefficient)):
        ExpandedFormSum.append(ExTerm2_Variable)
    if Term2.Coefficient < 0:
        TermSum =(Term1.SimTerm() + Term2.SimTerm())
    elif Term2.Coefficient >= 0:
        TermSum =(Term1.SimTerm() + "+" + Term2.SimTerm())

print(TermSum)
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

General

Attributes, variable names, function names and function arguments should be lowercase / snake_case.

You should wrap your main procedure in a main function, as well as a if __name__ == '__main__' guard. More info.

Documentation makes your code easier to read and understand. Use docstrings and comments to explain why and how your code is doing what it's doing.

Type hints make your code easier to read and understand, use them. PEP 484 | Python Docs


TermEva.__init__

self.ex_variable = ex_variable
if self.coefficient < 0:
    self.ex_variable = "-" + self.variable

Depending on the value of self.coefficient, self.ex_variable will either be a number or a string. Sticking to the number representation seems more intuitive here:

self.ex_variable = ex_variable
if self.coefficient < 0:
    self.ex_variable = self.variable * -1

On closer inspection, your main functionality always passes strings to the constructor of TermEva. I don't think this is intended, as your implementation of TermEva implies the arguments are numbers. You should generally check user input for correctness and then convert it to the desired type.


TermEva.sim_term

f-strings are a great tool for string formatting:

def sim_term(self):
    return f"{self.coefficient}{self.variable}"

TermEva.expanded_form

This pattern of list creation

expanded_form = []
for num in range(abs(self.Coefficient)):
    ExpandedForm.append(self.ExVariable)

can (and often should) be replaced by a more functional approach:

  • return [self.ex_variable for _ in range(abs(self.coefficient))]
  • return [self.ex_variable] * abs(self.coefficient)

Note that it's convention to use _ as a variable name for loop variables you don't actually use. This makes it immediately clear to the reader that the value of num is not needed.

\$\endgroup\$
2
\$\begingroup\$

Building on what @riskypenguin suggests:

  • TermEva is a slightly awkward name, and is simpler and clearer as Term.
  • Replace your SimTerm with a standard implementation of __str__.
  • Expanded_Form is not used, so you can just delete it; or if you want to keep it, you should be using join if it's only for print.
  • This is a clear application for a frozen dataclass that enforces immutability and writes your constructor for you. You can then include a @classmethod pseudoconstructor to centralize your input capture routine.
  • Consider implementing __add__ on the class.
  • An implementation that can generalize the "expanded form sum" as well as the basic two-term sum would separate the concept of a term and an equation, with the latter having its own class and holding references to terms in a list. I haven't shown this below.

Suggested

from dataclasses import dataclass
from numbers import Real


@dataclass(frozen=True)
class Term:
    variable: str
    coefficient: Real

    def __str__(self) -> str:
        return f'{self.coefficient:g}{self.variable}'

    @classmethod
    def from_stdin(cls, sequence: int) -> 'Term':
        return cls(
            input(f'Enter variable {sequence}: '),
            float(input('Enter its coefficient: ')),
        )

    @property
    def expanded_form(self) -> str:
        if not self.coefficient.is_integer():
            raise ValueError(f'Expanded form cannot be represented for {self}')

        n = int(abs(self.coefficient))

        if self.coefficient >= 0:
            return ' + '.join((self.variable,) * n)

        return ' - '.join((
            f'-{self.variable}',
            *((self.variable,) * (n - 1))
        ))

    def __add__(self, other: 'Term') -> str:
        if self.variable == other.variable:
            return str(Term(self.variable, self.coefficient + other.coefficient))

        if other.coefficient < 0:
            return f'{self} - {-other.coefficient}{other.variable}'
        return f'{self} + {other}'


def main() -> None:
    x = Term.from_stdin(1)
    y = Term.from_stdin(2)
    print(x + y)


if __name__ == '__main__':
    main()
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.