python:构造方法__init__( )

python魔法方法:__init__( )

1、__init__()方法称为构造方法,__init__()方法的魔力体现在只要实例化一个对象,这个方法就会在对象被创建时自动调用

2、实例化对象时是可以传入参数的,这些参数会自动传入__init__()方法中,可以通过重写这个方法来自定义对象的初始化操作

3、__init__()方法是一个特殊的方法,在对象实例化时会被调用,__init__()方法的作用是初始化。(初始化各个实例对象的实例属性。因此__init__方法也叫构造函数、构造方法)

4、其实也就是使用__init__()方法来定义每个实例对象独有的属性:实例属性(也叫实例变量)

5、一个抽象类可以实例化出无数个对象。每个对象都可以拥有自己自己的独特属性(实例变量),这些独特属性都是通过__init__方法来实现的 (通过给__init__方法定义和传入不同的实例变量来实现)

例1:

class Myclass:
    i = 123
    def __init__(self,friend):
        self.friend = friend

    def func(self,myself):    #带有参数的类方法
        return myself +"say hello to " + self.friend

use_class = Myclass("xiaoming") #实例化一个类对象
print("调用类的属性:",use_class.i)
print("调用类的方法:", use_class.func("xiaohong"))

"""
调用类的属性: 123
调用类的方法: xiaohongsay hello to xiaoming
"""

注:

1、在python中定义类时,如果没有定义__init__( )方法,则在类实例化时系统会自动调用默认的构造方法(无参数的__init__( )方法),另外__init__( )方法可以有参数,参数通过__init__( )传递到类的实例化操作上

2、一个类中可以定义多个构造方法(__init__( )),但是实例化类时只会实例化最后的构造方法,即后面的构造方法会覆盖前面的构造方法,并且需要根据最后一个构造方法的形式进行实例化(参数与最后一个构造方法的参数一致)。因此一个类中最好只定义一个构造方法

3、初始化实例包括:定义和初始化实例属性或调用类的一些方法

4、构造方法可以带有除self外的其它各种参数(关键字参数、默认参数、用元组收集参数、用字典收集关键字参数等),可以在实例化类时,传入对应的实参

5、定义实例变量:需要使用self来将变量绑定到实例上。self.friend = friend,表示将外部传来的参数friend的值赋值给Myclass类当前实例对象自己的实例属性friend

6、如果一个类定义了__init__方法且该方法中定义了除self参数之外的参数,那么在实例化这个类时就必须传入对应的实例变量的值(实参)

 

 

类的方法定义

语法:

def fun_name(self,...);

      Pass

注:

1、其中的参数self代表类的当前实例,在调用方法时由系统自动提供

2、方法定义时必须指明self参数,但是在调用类方法时,就不需要传递self参数了

3、简单的来说就是:self代表的当前的实例对象本身,这样在调用类方法等时Python就知道当前是哪个实例对象在调用了
    ⑴一个抽象类实例化后,实例对象为a,那么此时self就代表实例对象a
    ⑵一个抽象类实例化后,实例对象为b,那么此时self就代表实例对象b

 

 

类的方法的调用

类的方法的调用:与普通的函数调用类似
    ⑴类的内部调用:self.<方法名>(参数列表),或类名.方法名(self,参数列表)
    ⑵在类的外部调用:<实例名>.<方法名>(参数列表)
    ⑶注意:以上两种调用方法中,提供的参数列表中都不用包括self (类名.方法名(self,参数列表除外)

例2:

class Num:
    def eat(self,name):
        self.name = name
        print("mmm and %s" % self.name)

    def speed(self):
        self.eat("nn")           #类中访问方法:self.方法名
        #Num.eat(self,"nn")      #类中访问方法:类名.方法名(self)

num = Num()
num.speed()  #类外调用类方法:实例名.方法名

"""
mmm and nn
"""

 

 

__init__方法的默认参数

前面说到:构造方法可以带有除self外的其它各种参数(关键字参数、默认参数、用元组收集参数、用字典收集关键字参数等),可以在实例化类时,传入对应的实参

例3:

class Washer:
    def __init__(self,number):
        self.number = number #位置参数
        self.water = 0      #默认参数
        self.scour = 0      #默认参数

    def add_water(self, a):     #方法中的关键字参数
        print('a的值为', a)
        print("water的值为:",self.water)
        print("number的值为:", self.number)
        print("scour的值为:", self.scour)

    def start_wash(self,b=0):   #方法中的默认参数
        print("b的值为:",b)
        self.scour = 1          #在类中重新对实例变量重新赋值:但是会影响到后面的值(所以轻易不要用)
        print("scour的值为:", self.scour)

if __name__ == '__main__':
    w = Washer(2)
    w.add_water(10)
    w.start_wash()
    w.start_wash(2)

"""
a的值为 10
water的值为: 0
number的值为: 2
scour的值为: 0
b的值为: 0
scour的值为: 1
b的值为: 2
scour的值为: 1
"""

注:

1、这段代码中__init__方法中定义了四个参数:self,number,water,scour
    ⑴self:表示实例对象本身(谁调用,就表示谁)。语法上,类中的方法的第一个参数都是self,这是和普通方法区别的地方
    ⑵number:是在__init__方法中的定义的位置参数,在实例化对象时需要按位置传递值进来
    ⑶water、scour:是在__init__方法中的定义的默认参数,默认值为0(self.water = 0和self.scour = 0:跟函数的默认参数含义差不多)。且这种定义方式无法通过外部传值来修改其的值(如果需要改变其值只能对其重新赋值了,因此这种定义方式意义不大)

2、像这个例子中的这种定义默认值的方法一般都不会用到,因为无法通过外部传值来修改其的值

3、也可以看出来:其实在__init__方法中定义参数的方式与我们一般函数定义参数的方式是一样的,只是说__init__方法的第一个参数必须是self

 

例2_1:常用的默认值参数

class Washer:
    def __init__(self,number,water=0,scour=0):
        self.number = number
        self.water = water
        self.scour = scour

    def add_water(self, a):
        print('a的值为', a)
        print("number的值为:", self.number)
        print("water的值为:",self.water)
        print("scour的值为:", self.scour)

    def start_wash(self,b=0):
        print("b的值为:",b)
        self.scour = 1
        print("scour的值为:", self.scour)

if __name__ == '__main__':
    # 因为在__init__方法中定义了位置参数,那么在实例化类时就必须按位置传入对应变量的值
    w = Washer(2,3,4)#传了默认参数的值
    w.add_water(10)
    w.start_wash()
    w.start_wash(2)
    print("---------")
    s = Washer(2)   #不传默认参数的值
    s.add_water(1)

"""
a的值为 10
number的值为: 2
water的值为: 3
scour的值为: 4
b的值为: 0
scour的值为: 1
b的值为: 2
scour的值为: 1
---------
a的值为 1
number的值为: 2
water的值为: 0
scour的值为: 0
"""

注:

1、这个例子中的默认参数的第一方式才是经常使用到的:在实例化类时传了默认参数的值就用传的值,未传默认参数的值时就是用默认的值

2、上面例子中water=0 scour=0为默认参数,默认值为0和0:且这种写法也支持外部传入实参(self.water = water,self.scour = scour),当外部传入实参时,就用外部传入的参数,外部未传入实参时,就用默认值

3、这里self.water = water和self.scour = scour表示实例对象的属性:将外部传来的water和scour,赋值给了实例对象的water和scour属性(只是将形参的名字定义来跟实例属性名一致)

 

例2_2:__init__值为其他函数或方法的返回值

def add(a,b):
    return a + b

class Test():
    def __init__(self,y):
        self.x = add(1,2)
        self.y = y

    def func(self,c):
        return self.x + self.y + c

test = Test(3)
print(test.func(4))

#10

例2_3:

class Student():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def Name(self):
        return self.name

class From():
    def __init__(self):
        self.student = Student("张三",13)   #实例化另一个类并作为这个类的实例变量(属性)
        self.studentName = self.student.Name() #调用另一个类的方法,并将其返回值赋值给这个类作为实例变量(属性)

    def Info(self,address):
        info = "姓名:%s,来自于%s" % (self.studentName,address) #在类中调用自己类的实例变量(类中:self.实例变量名)
        return info

    def Age(self):
        return "年龄:%s" % self.student.age  #调用其他类的实例变量(类外:实例名.实例变量名,需要注意的是这里的实例名是self.student)

comfrom = From()
info = comfrom.Info("china")
age = comfrom.Age()
print(info)
print(age)

"""
姓名:张三,来自于china
年龄:13
"""

注:
1、构造方法可以带有除self外的其它各种参数:位置参数、关键字参数、默认参数、用元组收集参数、用字典收集关键字参数等。设置参数后,只需要在实例化类时,传入对应的实参即可

2、同样:在定义实例变量的值时,其值也可以是其他函数或方法的返回值,其实就跟在普通函数中变量的值时其他函数的返回值一样,只是说这里多了个self

3、这里主要是想说明下:在调用Student()类的实例变量age时,用的是"self.student.age",而不是"self.student.self.age"
    ⑴这个例子中Student()类的实例名是"self.student",因为它是作为From()类的实例变量存在的
    ⑵类中:self.实例变量名
    ⑶类外:实例名.实例变量名

例2_4: 

import cx_Oracle
class DB():
    def __init__(self):
        pass

    def ConnectDB(self,db_info="数据库信息"):
        try:
            db_conn = cx_Oracle.connect(db_info)
            db_cursor = db_conn.cursor()
            return db_conn, db_cursor
        except BaseException:
            raise ("数据库连接失败,请检查输入参数")

    def InsertSql(self,db_conn,db_cursor,sql):
        try:
            db_cursor.execute(sql)
            db_conn.commit()
            print("插入航班数据成功")
        except BaseException:
            db_conn.rollback()
            raise ("!!!插入失败!!!")

class ZUH_Moudle():
    def __init__(self):
        # 实例化另一个类,并将其实例名作为这个类的实例变量
        self.db = DB()      
        # 调用另一个类的方法,并将方法的返回值作为这个类的实例变量
        self.db_conn, self.db_cursor = self.db.ConnectDB(db_info="数据库信息")

    def InsertData(self):
        insertSql = "SQL语句"
        # 通过实例对象名,调用类的方法
        self.db.InsertSql(self.db_conn, self.db_cursor,insertSql)

注:在定义实例变量的值时,其值也可以是其他函数或方法的返回值,其实就跟在普通函数中变量的值时其他函数的返回值一样,只是说这里多了个self

 

例3:

class Car():
    def __init__(self,color_1,brand_1):
        self.color = color_1
        self.brand = brand_1
    def one_car(self):
        print("品牌:%s,颜色:%s" % (self.brand,self.brand))

car = Car("黑色","奔驰")
car.one_car()

#可以看出其实形参名可以不跟实例属性名一致,只是说一致时要方便点
#品牌:奔驰,颜色:奔驰

例4:

class  Num_add():
	a = 1                       #定义在类中但在函数体外的变量为类变量
    def __init__(self):         
        self.x = 4                  #这里的self.x,self.y就是实例变量
        self.y = 3
    def add(self):
        print(self.x + self.y)
number = Num_add()
number.add()

#上面代码的输出结果为:7

注:例子中定义了两个实例变量x和y,在后面的所有类方法中(类中)如果要用到这个两个变量,都需要通过"self.实例属性名"的写法来调用
    ⑴类中访问实例变量:self.实例变量名
    ⑵类外访问实例变量:实例名.实例属性名

例5:

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def Introduce(self):
        #在函数内部访问自己的属性和方法
        print("我叫%s,今年%d岁" % (self.name, self.age))

p = Person("hao",20)
p.Introduce()
#上面代码的输出结果为:我叫hao,今年20岁

注:在类的内部,访问自己的属性和方法,都需要通过self,self就是外部对象在类内部的表示

 

 

类补充

例6:

class Count():
    def __init__(self,a,b):
        self.a = int(a)   #实例变量也可以是一个函数等的返回值
        self.b = int(b)
    def Add(self,c):
        sum = self.a + self.b + c
        return sum

count = Count(1,2)
print(count.Add(3))

#6

上面例子中:__init__方法初始了a,b两个变量(属性),在类中的其他方法可以使用self.属性名调用这些参数(a,b),也可以拥有自己的参数(c)并直接调用

例6_1:

class Car():
    """这是一个汽车类"""
    brand = "宝马"
    color = "红色"

    def run(self,s):
        print("当前行驶速度:%s KM/S"% s)
        #print(self.__class__)

car = Car()
#调用类属性(调用类属性时,最好不要中这种方式)
print("品牌:%s,颜色:%s" % (car.brand,car.color))
#调用类方法
car.run(50)

"""
品牌:宝马,颜色:红色
当前行驶速度:50 KM/S
#
"""

注:
1、定义好类后,首先需要创建一个类的实例(实例化类后才能使用):python只需要类名+()就可以实例化一个类car = Car()

2、使用点(.)来调用属性和方法

3、self代表当前实例,而self.__class__就是Car类

 

 

类变量

1、上面例子中像brand、color这类变量叫做类变量,是所有类实例共享的变量:类变量定义在类中但是不属于任何函数

2、虽然可以向上面例子中那样使用类名来访问并修改类变量,但是不建议这么做,因为当使用"类名.类属性名"来修改了类变量后,可能会对其他类实例的使用造成影响。正确的用法是"实例名.属性"的方式访问类的属性

例7:

class Car():
    """这是一个汽车类"""
    brand = "宝马"
    color = "红色"

    def run(self,s):
        print("当前行驶速度:%s KM/S"% s)

a = Car()
b = Car()
print(a.brand,id(a.brand))
print(b.brand,id(a.brand))

"""
宝马 2620619371744
宝马 2620619371744
"""

注:可见两个实例的brand属性所指向的内存地址是相同的,这就意味着如果修改了Car.brand,那么实例a和实例b的brand值都会发生变化

例7_1:

Car.brand = "奔驰"
a = Car()
b = Car()
print(a.brand,id(a.brand))
print(b.brand,id(a.brand))

"""
奔驰 2276323505616
奔驰 2276323505616
"""

例7_2:

class Car():
    """这是一个汽车类"""

    brand = "宝马"
    color = "红色"


    def run(self, s):
        print("当前行驶速度:%s KM/S" % s)


a = Car()
b = Car()
print(a.brand, id(a.brand))
print(b.brand, id(a.brand))

a.brand = "奔驰"
print(a.brand, id(a.brand))
print(b.brand, id(a.brand))
"""
宝马 2193136297184
宝马 2193136297184
奔驰 2193136297424
宝马 2193136297424
"""

 

实例变量

1、类变量表示所有实例都拥有的属性(每个实例的属性都一致),那对于每个实例都不一样的属性(每个实例独有的属性)该怎么表示呢?对于这种类型的属性,可以使用实例变量来储存

2、实例变量是定义在方法(__init__)中的变量,只能用于当前类的实例

例8:

class Car():
    """这是一个汽车类"""
    def __init__(self,brand,color):
        self.brand = brand
        self.color = color

    def run(self,s):
        print("当前行驶速度:%s KM/S"% s)

    def print_car(self):
        print("品牌:%s,颜色:%s" % (self.brand,self.color))


car_A = Car("宝马","红色")
car_A.print_car()

car_B = Car("奔驰","黑色")
car_B.print_car()

print(car_A.brand)
print(car_B.color)

"""
品牌:宝马,颜色:红色
品牌:奔驰,颜色:黑色
宝马
黑色
"""

注:

1、实例变量表示:每个实例独有的属性,需要定义在__init__方法中

2、方法__init__()叫做构造函数,每当实例化一个类时都会执行这个函数,通常会在这个函数里面为实例属性进行初始化

3、存在构造函数时,在实例化类时就必须传入实例变量的实参:car_A = Car("宝马","红色"),当然如果方法中存在参数,那在调用类的方法时也必须传入实参

4、在类中调用实例属性时为:self.属性名,在类外调用实例属性时为:实例名.属性名


 

拓展

例9:

class Employee(object):
    """所有员工的基类"""
    empCount = 0
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1#修改类变量的值

    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)

    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)


#创建Employee类的第一个对象
emp1 = Employee("Zara", 2000)
emp1.displayEmployee()
print("Total Employee %d" % Employee.empCount)

#创建 Employee 类的第二个对象
emp2 = Employee("Manni", 5000)
emp2.displayEmployee()
print("Total Employee %d" % Employee.empCount)
# 添加一个 'age' 属性
emp1.age = 7#增加实例属性
# 修改 'age' 属性
emp1.age = 8
# 删除 'age' 属性
print("emp1年龄为:",emp1.age)

emp2.age = 9
print("emp2年龄为:",emp2.age)


"""
Name :  Zara , Salary:  2000
Total Employee 1
Name :  Manni , Salary:  5000
Total Employee 2
emp1年龄为: 8
emp2年龄为: 9
"""

 

 

总结

__init__方法
1、实例属性是在__init__方法中定义的:表示各个实例所独有的
2、__init__方法中第一个参数始终是self:代表当前具体的实例
3、__init__方法定义格式为:

class Studeng():
    def __init__(self,name,score):
        self.name = name
        self.score = score


4、上面示例的意思为:把外部参数name的值(形参)传递给具体实例的name属性(也算是一个形参吧,只是实例属性名与外部形参名一致),用self将属性绑定到具体的实例上,明确当前属于哪个实例


self参数
1、self参数是实例对象在类内部的表示(即:self表示实例对象)
2、类方法在定义时,第一个参数始终是self参数:告诉python当前是哪个实例在调用方法
3、在类中调用实例属性时,格式为self.属性名:告诉python当前是哪个实例在调用属性(该属性属于哪个实例)

 

 

Python类中的__init__()构造方法

1、构造方法__init__用于定义类的实例变量(每个实例独有的属性)
2、调用实例属性:
    ⑴在类中调用实例属性时为:self.属性名
    ⑵在类外调用实例属性时为:实例名.属性名
    
例5:正确的写法

class Count():
    a = 1
    def __init__(self, x, y):
        self.x = int(x)
        self.y = int(y)

    def Add(self, c):
        sum = self.x + self.y + c
        return sum

    def Subtract(self):
        subtract = self.x - self.y - 1
        return subtract

count = Count(2, 3)

print(count.Add(2))
print(count.Subtract())

"""
7
-2
"""

注:
1、这个例子中涉及到了三种类型的变量:
    ⑴类变量a:直接定义在类中的变量
    ⑵实例变量x和y:定义在__init__方法中的变量
    ⑶函数内的局部变量c:定义在方法中的变量,作用域在该函数内

2、这里例子中的局部变量c只能在定义的方法内使用,即使是同一个类中的其他方法也不能调用这个变量

3、这个例子是正确的写法:完全把变量c当做局部变量只能在定义的方法中调用,其他方法都不能调用(既然是定义在方法内的,那么本来就没打算让其他方法调用)
 

例5_1:

class Count():
    a = 1
    def __init__(self, x, y):
        self.x = int(x)
        self.y = int(y)

    def Add(self, c):
        sum = self.x + self.y + c
        return sum

    def Subtract(self):
        subtract = self.x - self.y - c
        return subtract

count = Count(2, 3)

print(count.Add(2))
print(count.Subtract())

"""
NameError: name 'c' is not defined
"""

注:
1、可以看出:局部变量c只能在定义的方法内使用,即使是同一个类中的其他方法也不能调用这个变量

2、如果想在其他方法中调用这个局部变量的话,那可以修改下定义方法

例5_2:

class Count():
    a = 1
    def __init__(self, x, y):
        self.x = int(x)
        self.y = int(y)

    def Add(self, c):
        self.c = c
        sum = self.x + self.y + self.c
        return sum

    def Subtract(self):
        subtract = self.x - self.y - self.c
        return subtract

count = Count(2, 3)

print(count.Add(2))
print(count.Subtract())

"""
7
-3
"""

注:
1、这个例子中就将Add()方法中的局部变量c定义成了一个:类似于实例变量的变量(实际上不是实例变量,因为它不会被__init__方法初始化)。这样就可以在其他方法中调用这个局部变量了

2、不过这样写法的话,就必须先执行Add()方法再执行Subtract()方法了,如果直接执行Subtract()方法,那么就会找不到变量c的值

3、当然,我这里只是说明下这么写不会报错,但是实际上这种写法是不对的
    ⑴如果你想一个变量能被多个方法调用,那还不如直接定义在__init__方法中或定义为类变量
    ⑵既然是将变量定义在了一个方法内(局部变量),那么肯定是不想被其他方法调用的,那写成"self.c = c"就没任何意义了
    ⑶并且这种写法的话,在调用上很不方便:其他方法在调用这个变量前必须先调用这个定义变量的方法,不然就报错了
    ⑷一句话:类变量就是类变量、实例变量就是实例变量、局部变量就是局部变量

例5_3:

class Count():
    a = 1
    def __init__(self, x, y):
        self.x = int(x)
        self.y = int(y)

    def Add(self, c):
        self.c = c
        sum = self.x + self.y + self.c
        return sum

    def Subtract(self):
        subtract = self.x - self.y - self.c
        return subtract

count = Count(2, 3)

#print(count.Add(2))
print(count.Subtract())

"""
AttributeError: 'Count' object has no attribute 'c'
"""

 

你可能感兴趣的:(python3,python,构造方法)