面向对象学习笔记(一)
- 基础定义的梳理与理解
①、类的定义和类变量的定义:这是类,只能有一个,做好了定义,没有具体的值
class Bird:
def __init__(self,length,height,color):
self.length = length
self.height = height
self.color = color
>>> b=Bird(10,20,"red")
>>> b
<__main__.Bird object at 0x00000000023E1BA8>
>>> c=Bird(5,6,"yellow")
>>> c
<__main__.Bird object at 0x0000000002428EF0>
>>> b.color
‘red’
>>> c.color
‘yellow’
类的定义在内存中某个地址存储,且只有一份
class Bird:
#构造方法:主要设定实例中的参数
def __init__(self,length,height,color):
self.length = length
self.height = height
self.color = color
#实例方法
def get_color(self):
return self.color
生成一个实例,那么实例就保存在内存的某个地址
b=Bird(10,20,"red")
print(b.get_color())#python调用实例方法时候
#会自动给你传实例给方法
#get_color(b)
b和c在内存中是各自独立保存,互相不影响
b.color="black"
print(b.color)
print(c.color)
del b
print(c.color)
原理:类(类变量,方法)在内存中只有一个地方存储,那么类中定义的方法也在那个地方存储。
当时实例想调用某个类中定义的方法时,需要把实例对象传递给类中定义的方法,才能够使用。
python默认把实例地址,自动传递给方法中的self,这样就可以找到不同实例中的实例变量
②、区分类对象和实例对象
类:模板–》简历模板—》类(没有具体的数据)
以下为生成的实例:包含有具体的信息
姓名、性别,个人信息—》小张的简历–》小张的实例
姓名、性别,个人信息—》小李的简历–》小李的实例
姓名、性别,个人信息—》小赵的简历–》小赵的实例
共同点:都是使用模板来生成的
不同点:每个生成简历内容都是不一样的
class Resume:#简历模板,类对象
def __init__(self,name,age):
self.name = name
self.age = age
xiaozhang_resume = Resume("小张",28)#为实例,实例对象
xiaoli_resume = Resume("小李",28)
xiaozhao_resume = Resume("小赵",28)
print(xiaozhang_resume.name)#对象:类对象和实例对象
③、类、类变量以及数据成员定义
(1)在类里面实现的叫方法;在类外面实现的叫函数
(2)类是由变量组成的,其中变量包括实例变量和类变量以及操作他们的方法,还有局部变量
(3)类的本质:把需要管理的数据封装到实例里面,然后基于类中的方法定义规则,以此来实现业务数据的完整性和一致性(防止出现脏数据)
(4)类的定义:类在内存中只有一份地址,而每个实例在各自在内存中保存的地址,各自独立
(5)数据成员:类里面的变量就叫数据成员,无论是类变量还是实例变量还是局部变量,都是数据成员
class Person:
count = 0 #类变量
def __init__(self,name):
self.name = name#self.name是实例变量,name是局部变量
def get_name(self):
return self.name
def set_name(self):
self.name = "great"
>>>
>>> zhaolaoshi = Person("赵老师")#实例化的过程,因为有name所以要传一个参数
>>>
>>> zhaolaoshi .name
‘赵老师’
>>> zhaolaoshi .get_name()
‘赵老师’
④、java的构造函数的实现方法:
//package cn.great.test
public class HelloWorld
{
String name;
public HelloWorld(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public static void main(String[] args){
System.out.println("Hello world!");
HelloWorld hw = new HelloWorld("great");
System.out.println(hw);
System.out.println(hw.getName());
}
}
⑤、方法重写的概念:
父类里面有get_name方法,子类也有get_name方法,会覆盖父类中的方法
class Person: #父类
def __init__(self,name):
self.name = name
def get_name(self):#self:传递的参数是实例的内存地址
# #告诉这个方法,使用哪个实例的数据
return self.name
def set_name(self,value):
self.name = value
class Teacher(Person): #子类
def __init__(self,name):
Person.__init__(self,name)
#父类如果不只有self,且有其他参数。那么子类需要调用父类的构造方法来初始化
#self.name = name
self.salary = salary
t = Teacher("赵老师")
print(t.get_name())
2、类和实例
类:类是一个模板,它描述一类对象的行为和状态。
创建类
class Foo:
def Bar(self):
print ('Bar')
def Hello(self, name):
print('i am %s'%name)
#根据类Foo创建对象obj
obj=Foo()
obj.Bar() #执行Bar方法
obj.Hello('Mr.Right') #执行Hello方法
①、查看类的文档字符串__doc__
类的帮助信息可以通过ClassName.__doc__查看
class Person:
Count = 0
def __init__(self,name):
self.name = name
def get_name(self):
"""获取名字"""
return self.name
def set_name(self,value):
self.name = value
class Teacher(Person):
'''此类主要用于管理老师的数据'''
def __init__(self,name,salary):
Person.__init__(self,name)
self.salary = salary
Teacher.Count+=1
self.Count = 100
s = Teacher("李老师",2000)
print(s.get_name())
print(s.get_name.__doc__)
3、类变量
①、类变量通过类名或者实例变量调用
class Person: #父类
Count = 0
def __init__(self,name):
self.name = name
def get_name(self):
return self.name
def set_name(self,value):
self.name = value
class Teacher(Person): #子类
def __init__(self,name,salary):
Person.__init__(self,name)
self.salary = salary
Teacher.Count+=1
t = Teacher("赵老师",1000)
s = Teacher("李老师",2000)
print(Teacher.Count)
print(t.Count)
②、类变量和实例变量同名,实例变量会被优先访问
类变量和实例变量同名,实例变量会被优先访问实例变量中找不到会去类变量中找
类变量的使用方法:类名.类变量名
class Person: #父类
Count = 0
def __init__(self,name):
self.name = name
print(id(self.name))
def get_name(self):
return self.name
def set_name(self,value):
self.name = value
class Teacher(Person): #子类
def __init__(self,name,salary):
Person.__init__(self,name)
self.salary = salary
Teacher.Count+=1
self.Count = 100 #与类变量同名,实例变量会覆盖类变量
t = Teacher("赵老师",1000)
s = Teacher("李老师",2000)
print(Teacher.Count)
print(t.Count)
4、访问类的实例方法或属性
print(self.name)#跨方法调用实例变量,self.xxx
print(self.get_name())#跨方法调用实例方法,self.方法名
class Person: #父类
Count = 0
def __init__(self,name):
self.name = name
print(id(self.name))
def get_name(self):
return self.name
def set_name(self,value):
self.name = value
class Teacher(Person): #子类
def __init__(self,name,salary):
Person.__init__(self,name)
self.salary = salary
Teacher.Count+=1
def print_info(self):
print(self.name)#跨方法调用实例变量,self.xxx
print(self.get_name())#跨方法调用实例方法,self.方法名
t = Teacher("赵老师",1000)
s = Teacher("李老师",2000)
t.print_info()
5、类的方式实现两个小怪物打架
blood=100
exp = 0
如果打架了,内部看经验值,谁经验值大,-5,谁经验少-10
经验值相等就都-5
经验值:减血多的+10,减血少的+5
class Solider:
def __init__(self,name):
self.name = name
self.blood = 100
self.exp = 0
self.alive_flag = "alive"
def fight(self,enemy):#self是s1,enemy是s2,都是Soldier的实例
print("%s 遇到了一个敌人%s,开打" %(self.name,enemy.name))
if self.exp > enemy.exp:
self.sub_blood(5)
enemy.sub_blood(10)
self.add_exp(5)
enemy.add_exp(10)
elif self.exp == enemy.exp:
self.sub_blood(5)
enemy.sub_blood(5)
self.add_exp(5)
enemy.add_exp(5)
else:
self.sub_blood(10)
enemy.sub_blood(5)
self.add_exp(10)
enemy.add_exp(5)
print("%s 遇到了一个敌人%s,打完了" %(self.name,enemy.name))
def sub_blood(self,value):
if isinstance(value,(int,float)):
self.blood-=value
print("%s掉了%s血" %(self.name,value))
if self.blood<=0:
self.alive_flag = "dead"
self.blood=0
print("%s被打死了" %self.name)
def add_exp(self,value):
if isinstance(value,(int,float)):
self.exp+=value
print("%s涨了%s经验" %(self.name,value))
s1 = Solider("张三")
s2 = Solider("李四")
s3 = Solider("王五")
s4 = Solider("赵璐")
scerio=[]
#4个战士的实例,放到了scerio
scerio.append(s1)
scerio.append(s2)
scerio.append(s3)
scerio.append(s4)
import random
times=0
while times<20:
times+=1
s1=random.choice(scerio)#取的是某个战士的实例
s2=random.choice(scerio)#取的是某个战士的实例
if s1!=s2:#s1传给了self,s2传给了enemy,都是战士的实例
s1.fight(s2)#s1传给self,s2传给了enemy
else:
continue
for i in scerio:
print("%s 还有%s血,%s经验,%s" %(i.name,i.blood,i.exp,i.alive_flag))
6、类和对象在内存中是如何保存
①、类和实例:
类 存的是类变量和所有方法
实例 存的是实例变量 和类对象指针(也就是类的内存地址)
②、类对象和实例对象在内存中的存储方法
对象包括类对象和实例对象
类对象:在内存中,只存一份类变量和类中定义的相关方法
实例来说:每个实例的数据都互相独立的,那么在内存,每一个实例,占有一个独立的内存地址空间
7、面向对象的三大特征:封装、多态、继承
封装:将内容封装到类里面,然后再去调用被封装在某处的内容
8、类方法、静态方法、实例方法
class P:
def__init__(self,name): #实例方法有个self
self.name = name
def print_info(self):
print("info method is invoked!")
@classmethod
def print_sth(cls): #类方法需要有@classmethod,还要有cls,
#不能使用实例变量
#print(self.name)
print("class method is invoked!")
@staticmethod
def print_p():#静态方法需要有@staticmethod,可以有参数也可以没有,
#不能使用实例变量
print("static method is invoked!")
a=P("赵老师")
a.print_info()#通过实例调用实例方法
P.print_sth()#通过类名调用类方法
a.print_sth()#通过实例调用类方法
P.print_p()#通过类名调用静态方法
a.print_p()#通过实例调用静态方法
总结:
类方法需要有@classmethod,还要有cls, 不能使用实例变量
静态方法需要有@staticmethod,可以有参数也可以没有, 不能使用实例变量
实例方法有个self
9、@property属性
①、调用属性时候,等价于调用了prop方法,获取返回值。
#encoding=utf-8
class Foo:
def func(self):
print ("func!")
# 定义属性
@property
def prop(self):#self是实例方法,得用实例调用
return "great"
foo_obj = Foo()
foo_obj.func()
print (foo_obj.prop) #调用属性时候,等价于调用了prop方法,获取返回值
class Goods(object):
@property
def price(self):
print ('@property')
@price.setter
def price(self, value):
print ('@price.setter')
@price.deleter
def price(self):
print ('@price.deleter')
g = Goods()
g.price #调用@property方法
g.price=100 #调用了price.setter方法
del g.price # 调用了@price.deleter方法
属性的本质:
1 当你读取属性的时候,执行@property方法
2 当你修改属性的时候执行@price.setter方法
3 当你删除属性的时候执行@price.deleter
①下面代码出现了脏数据
class Goods(object):
def __init__(self):
self.price =0
def set_price(self,value):
if isinstance(value,(int,float)) and value>=0:
self.price=value
g = Goods()
g.set_price(10)
print(g.price)
g.set_price(-10)
print(g.price)
g.price=-10
print(g.price)
②下面代码屏蔽了脏数据
class Goods(object):
def __init__(self):
self.__good_price =0
@property
def price(self):
return self.__good_price
@price.setter
def price(self, value): #-10传给了value
if isinstance(value,(int,float)) and value>=0:
self.__good_price=value
g = Goods()
g.price=-10
print(g.price)