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
"""
前面说到:构造方法可以带有除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当前是哪个实例在调用属性(该属性属于哪个实例)
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'
"""