1

While practicing OOP with inheritance in my second class I have problems adding my parameters, as you can see I have: (self, name, tred, PM, PM2, ra, ra2). But when run the program it tells me that I can not multiply Nonetype, I print them to see what's wrong and i get that some of the parameters are incorrect.

The first class works fine (Atomic_d), I just need to understand how does it work the variables in the second class: Molecular_d

How can I fix this?

This is the complete code picture

import math
class Atomic_d():
    def __init__(self,name="",red="",PM=None,ra=None):
        self.name = name
        self.red = red
        self.PM = PM
        self.ra = ra

    def density(self):
        redes = {"BCC":2,"FCC":4,"HCP":6}
        self.red = self.red.upper()
        nred = redes.get(self.red)
        nav = round(6.022*(10**23),3)

        if nred == 2:
            a = (4*(self.ra))/((3)**0.5)
        elif nred == 4:
            a = (4*(self.ra))/((2)**0.5)
        else:
            per = round(12 * self.ra,3)
            hipoc = round((2*self.ra)**2,3)
            basec = round(self.ra**2,3)
            apo = round(math.sqrt(hipoc - basec),3)
            a = round((per * apo / 2),3)

        if nred == 2 or nred == 4:
            vol = a**3
        elif nred == 6:
            vol = round(a * 3.266 * self.ra,3)
        
        density = round((((nred*self.PM)/(nav*vol))*10**21),3)
        return "{} : {} g/cc".format(self.name,density)

class Molecular_d(Atomic_d):
    def __init__(self,name="",tred="",PM=None,ra=None,PM2=None,ra2=None):
        super().__init__(name,PM,ra)
        self.PM2 = PM2
        self.ra2 = ra2
        self.tred = tred
    
    def density(self):
        tredes = {"NACL":8}
        self.tred = self.tred.upper()
        nred = tredes.get(self.tred)
        nav = round(6.022*(10**23),3)
    
        if nred == 8:
            l = round(((2*self.ra)*(2*self.ra2)),3)
            vol = l**3
        
        density = ((8*(self.PM + self.PM2))/(nav*vol))
        return "{}: {} g/cc".format(self.name,density)

This is the error that happens when I try to debug I print every variable to see what is the problem

    print("Hi I'm name",self.name)
    print("Hi I'm ra",self.ra)
    print("Hi I'm ra2",self.ra2)
    print("Hi I'm PM",self.PM)
    print("Hi I'm PM2",self.PM2)

Hi I'm name Ox de magnesio
Hi I'm ra None
Hi I'm ra2 0.14
Hi I'm PM 16.0
Hi I'm PM2 0.072

Traceback:

TypeError                                 Traceback (most recent call last)
<ipython-input-21-bb7a69690a34> in <module>
      1 magnesium_ox = Molecular_d("Ox de magnesio","NaCl",24.31,16.0,0.072,0.14)
      2 
----> 3 magnesium_ox.density()

<ipython-input-19-064f60b8cfce> in density(self)
     52 
     53         if nred == 8:
---> 54             l = round(((2*self.ra)*(2*self.ra2)),3)
     55             vol = l**3
     56 

TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
martineau
  • 119,623
  • 25
  • 170
  • 301
Bopemagno
  • 15
  • 5
  • 1
    In `super().__init__(name,PM,ra)`, you aren't passing `red`, which means that `ra` at the end isn't being filled. In a case like this, it doesn't make much sense to have `=None` defaults, since the object is "invalid" if any of the data is missed. Without the defaults, you would have gotten an error. – Carcigenicate Sep 20 '20 at 22:50

3 Answers3

0

When you make the call to super()_init(), you leave out the red argument. Python assumes that the three arguments you are passing are name, red, and pa, even though that's seems not to be what you intended.

When you don't attach parameter= to an argument, Python assumes you are giving them from left to right. You need to write:

super().__init__(name=name, PM=PM, ra=ra)
martineau
  • 119,623
  • 25
  • 170
  • 301
Frank Yellin
  • 9,127
  • 1
  • 12
  • 22
0

You need to be using keyword arguments if you are not going to put them same order as the class. Try changing the Molecular_d to this below:

class Molecular_d(Atomic_d):
    def __init__(self,name="",tred="",PM=None,ra=None,PM2=None,ra2=None):
        super().__init__(name=name,PM=PM,ra=ra)
        self.PM2 = PM2
        self.ra2 = ra2
        self.tred = tred
    
    def density(self):
        tredes = {"NACL":8}
        self.tred = self.tred.upper()
        nred = tredes.get(self.tred)
        nav = round(6.022*(10**23),3)
        
        if nred == 8:
            l = round(((2*self.ra)*(2*self.ra2)),3)
            vol = l**3
        else: 
            vol = 10
        
        density = ((8*(self.PM + self.PM2))/(nav*vol))
        return "{}: {} g/cc".format(self.name,density)

mag =  Molecular_d(name="a", tred="as", PM=1.1, ra=0.2, PM2=2.3, ra2=40.1)

result = mag.density()
print(result)
<< 'a: 4.5167718365991366e-24 g/cc'

I added in a default value of vol, because i'm not sure

0

You have that:

class Atomic_d():
    def __init__(self,name="",red="",PM=None,ra=None):

But, initialization is:

class Molecular_d(Atomic_d):
    def __init__(self,name="",tred="",PM=None,ra=None,PM2=None,ra2=None):
        super().__init__(name,PM,ra)

it:

super().__init__(name,PM,ra)

goes to:

def __init__(self,name="",red="",PM=None,ra=None):

as

__init__(self,name=name,red=PM,PM=ra,ra=None):

So, ra param was not initialised.

mrvol
  • 2,575
  • 18
  • 21