类与对象

类和对象

类就是抽象的概念
对象就是类生成的具体事例
属性就是类和对象所具有的事物的性质
方法就是类和对象的执行函数

例子:
人是一个抽象的类
你我他是类具体而成的对象
属性就是人这个类所具有的性质,比如说,身高体重头发颜色单双眼皮
方法就是人或者你我他能干的事,比如说,站,坐,躺,吃,喝

 1 class Cat:
 2     #属性
 3     #方法
 4     def xxx(self):#此处必须写self   ====>同等于this指针指向当前的对象
 5         print "123"
 6         
 7 redcat=Cat()
 8 #与c语言不同之处,可以直接添加,而不需要在类里面定义
 9 redcat.name="redcat"

 

__init__()函数

__init__的执行过程

1. 创建一个对象
2. python会自动调用__init__方法
3. 返回创建的对象的引用给对象
什么是引用,可以理解为当前这个对象是放在内存中的,我们找到这个内存,把这个内存的编号给了贴上这个对象的“标签”

(偷懒拷贝了一下)

1 class Cat:
2     #属性
3     #方法
4     def xxx(self):#此处必须写self   ====>同等于this指针指向当前的对象
5         print "123"        
6     def __init__(self):
7         #__init__同等于c语言的构造函数   为默认

或许你不知道什么事构造函数,这没什么关系,名字而已,理解它就行了。

例如以下代码

1 class Cat():
2     def __init__(self,new_name,new_age)
3         self.name=new_name
4         self.age=new_age
1 redcat=Cat("redcat",1)
2 bluecat=Cat("lanmao",2)

 

此时
cat1=Cat(参数1,参数2)
自动调用__init__函数
添加属性
当前对象name=参数1
当前对象age=参数2
相信很好理解吧。

__str__()函数

就上面那个例子而言,假如我们生成了对象redcat和bluecat,此时我们

print(redcat)
print(bluecat)

当然会报错

除非我们使用了这个函数

def __str__(self)
    return 你想打印出来的话(把类的属性用上,形如self.xxx 。当然不用也可以)

然后print这个对象,就会出现上面那句话了

例子

 1 class Student:
 2     def __init__(self,new_name,new_age,new_ID)
 3         self.name=new_name
 4         self.age=new_age
 5         self.ID=new_ID
 6         
 7     def __str__(self)
 8         return "%s的年龄是%s,学号是%s"%(self.name,self.age,self.ID)
 9         
10         
11 #然后我们生成对象
12 
13 xiaoming=Student(xiaoming,12,1)
14 
15 #打印小明的信息
16 
17 print(xiaoming)

那么此时假如小明有一只猫呢
我们可以这样(继续偷懒,复制上面的代码)

 1 class Student:
 2     def __init__(self,new_name,new_age,new_ID,new_cat):
 3         self.name=new_name
 4         self.age=new_age
 5         self.ID=new_ID
 6         self.cat=new_cat
 7     def __str__(self):
 8         message="%s的年龄是%s,学号是%s"%(self.name,self.age,self.ID)
 9         message+=",拥有的猫是%s,猫的年龄是%s" %(self.cat.name,self.cat.age)
10         return message
11     
12 
13     
14 class Cat():
15     def __init__(self,new_name,new_age):
16         self.name=new_name
17         self.age=new_age
18 
19 tom=Cat("tom",1)        
20     
21 xiaoming=Student("xiaoming",12,1,tom)
22 
23 print(xiaoming)

 更好一点的表达

当我们定义一个类,生成一个对象后,想让这个对象有自己的属性。

我们可以这样

1 class Cat:
2     pass
3 
4 cat1=Cat()
5 
6 cat1.name="虹猫"
7 cat1.age=1

或者这样

1 class Cat:
2     pass
3 
4     
5 cat1=Cat()
6 
7 cat1.get_name()
8 cat1.get_age()

那么两种方法当然是有去别的,孰优孰劣呢

假设这时我们再生成一个对象

1 cat2=Cat()
2 
3 cat2.age=-1

从语法上是正确的,但逻辑上并不对
所以推荐使用通过函数来获得属性
直接赋值存在一定的风险

更完美的表达应该是这样:

1 class Cat:
2     def get_name(self,new_name):
3         self.name=new_name
4     def get_age(self,new_age):
5         if new_age<0 or new_age >20
6             new_age=0
7         self.age=new_age

 

私有方法

就是在方法前加两条下划线

需要满足一定的条件,才能使用其他的方法调用这个私有方法
才能使用这个私有方法

 1 class Cat:
 2     #私有方法
 3     def __eat_fish():
 4         print "猫在吃鱼"
 5     
 6     def eat(self,age):
 7         if age>=1 and age<5
 8             self.__eat_fish()
 9         elif age>=5
10             print "猫的年龄太大了,不能吃鱼"
11         else
12             print "猫的年龄太小了,不能吃鱼"
13             
14 cat1=Cat()
15 cat1.eat(5)    

__del__()函数

类似于c++的析构函数

在对象被彻底删除时(不是标签被删除)
引用计数为0时
一定会调用这个方法

1 class Cat:
2     #私有方法
3     def __del__():
4         print "猫死了"
5     
6             
7 cat1=Cat()
8 print "================================="

但是结果却是

===================================
猫死了

因为程序结束,内存释放了

但是假如代码变成这样

class Cat:
    #私有方法
    def __del__(self):
        print "猫死了"

print "==============================="
cat1=Cat()
del cat1
print "==============================="
cat1=Cat()
cat2=cat1
del cat1
print "==============================="
del cat1

结果却是因为引用计数不为0,前面已经说过引用的问题,这里就不多讲了。

那么怎么测引用计数呢

1 impore sys
2 sys.getrefcount(要测的计数对象)

就会得到实际引用计数+1的结果。但当引用计数为0时,程序会抛出异常。

 函数重写

python中的继承的函数重写

大概是介个样子

 1 class A:
 2     def a(self):
 3         print "1"
 4 
 5 class B(A):
 6     def a(self):
 7         print "2"
 8 
 9 a=A()
10 a.a()
11 b=B()
12 b.a()

输出结果当然没有疑问,因为A中的a()方法在B中已经被重写了

那假如我铁了心就要调用那个怎么办呢   

可以这样

 1 class A:
 2     def a(self):
 3         print ("1")
 4 
 5 class B(A):
 6     def a(self):
 7         A.a(self)
 8         print ("2")
 9 
10 a=A()
11 a.a()
12 b=B()
13 b.a()

or这样

class A:
    def a(self):
        print ("1")

class B(A):
    def a(self):
        super().a()
        print ("2")

a=A()
a.a()
b=B()
b.a()

一些想法

 1 class A:
 2     def a(self):
 3          print ("1")
 4 
 5 class B(A):
 6     def a(self):
 7     #    super().a()
 8         print ("2")
 9 
10 class C(B):
11     pass
12 
13 a=A()
14 a.a()
15 b=B()
16 b.a()
17 c=C()
18 c.a()

结果是

1
2
2

 1 class A:
 2     def a(self):
 3          print ("1")
 4 
 5 class B(A):
 6     def a(self):
 7     #    super().a()
 8         print ("2")
 9 
10 class C(B):
11     pass
12 
13 a=A()
14 a.a()
15 b=B()
16 b.a()
17 c=C()
18 c.a()

结果为

1
1
2
1
2

重写方法并不是这个子类重写,以后继承这个子类的方法都会被重写
那假如就想只用最开始方法怎么办
重写喽,或者未来我学到更好的办法再补上来

 1 class A:
 2     def a(self):
 3          print ("1")
 4 class B(A):
 5     def a(self):
 6 #    super().a()
 7         print ("2")
 8 
 9 class C(B):
10     def a(self):
11         A().a()
12     pass
13 a=A()
14 a.a()
15 b=B()
16 b.a()
17 c=C()
18 c.a()

结果为
1
2
1

就又重写回来了

posted @ 2017-11-12 21:04  newen  阅读(215)  评论(0)    收藏  举报