python编程:python语言是一门完全面向对象对象的编程语言
使用class关键字,创建了一个dog类,内部有方法bulk方法,bulk上有self表示调用该对象的本身,类似java中的this
下面是申明三个狗对象
然后都去调用bulk方法,三个狗都在叫,输出bulk
如果要是想不通过对象来调用类中的方法,可以直接类名.方法名来调用所想调用的方法
self.name=name这个怎么理解,理解为当前对象增加一个name的实例变量其值为name参数
如果self.NAME=name这个理解为当前对象增加一个NAME的实例变量其值为name参数
这个程序和上面不同的是:
这里有一个构造方法__init__(self,name),构造方法的作用就是实例化使对类进行初始化的操作
我们在申明对象的时候,会自动调用他,申明对象传递参数1,2,3的时候,他会将参数1,2,3赋值给方法参数name,然后方法体内self.name=name,就表示这个对象的name属性赋值为name,self可以看成类似this,表示本对象
我们可以发现在python的类中,每个方法都有一个self的参数,这个参数就表示当前的对象,但是我们在调用函数的时候并没有传递self参数,之所以不报错是因为当我们d1.bulk()的时候,python会内部将其转成了Dog.bulk(d1),此时d1正好对应参数self,所以不会出粗,我们在方法内部可以通过这个参数self来获取当前对象的属性。
实例变量和类变量
实例变量是赋值给具体的实例,也就是具体的一个对象,而类变量是赋值给所有的对象,只要是这个类的实例就拥有这个类变量
定义在__init__初始化方法中的变量就是实例变量,定义在类中方法之外的变量就是类变量
我们称实例变量为静态属性,称类中的方法为动态属性比如从这个类的角度来说,n就是类变量被所有的实例对象所共享,类变量可以通过(类点类变量名)的方式来调用,而init方法内部的这些变量是实例变量,只为具体的对象服务。
当实例变量和类变量同名的时候,使用对象名来调用的这个变量的时候,会调用实例变量,也就是说实例变量具有更高的优先级,如果调用一个变量的时候,没有找到实例变量此时才会去类变量中查找。
当我们拥有一个对象的时候,我们可以通过这个对象点的方式来获取类变量或者实例变量,也可以通过对象点的方式来为对象添加一个实例变量。比如print d1.name,那么如果有这个实例变量那么就会输出当前这个d1对象的name值,如果没有实例变量但是有类变量就会输出当前类的类变量值,而d1.age=11,在当前的类中并没有这个实例变量,所以这个操作时为了给当前的对象d1添加一个实例变量age,并且赋值为11.
重点:这个类中有一个类变量n,我们可以通过对象.n的方式来获取这个类变量的值,假如我们使用
对象点n=100
这句话如何理解
如果理解为将类变量的n值修改为100就错了,这句代码的真实含义是为当前对象添加一个实例变量n值为100,这样当前对象就增加了一个实例变量n,也就是说对象只能获取当前的类变量值,但是不能修改类变量值
如果有一个类变量为h_list,当我们通过对象.h_list.append("22")的时候,这句话是怎么理解
如果将这句话理解为为对象添加一个h_list的实例变量就错了,这并没有赋值操作。所以不是添加成员变量,而是直接操作类变量,并给类变量h_list添加“22”,这个添加的22,在所有的对象中都可以通过h_list类变量获取到
要想修改类变量的值,可以通过类名.类变量的方式来修改,也可以通过这种方式来获取类变量的值
既然能够增加实例变量。那么同时也就可以删除实例变量,可以使用 del 对象点实例变量名 的方式来删除类中的实例变量,删除之后,这个实例变量就像是没有一样了
类变量的作用:类变量所有的对象共用一份,在内存中只存在一份
实例变量:每个对象都有一份,一个改变其他的不变
析构函数:def __del__(self):
当实例释放或者销毁的时候,做一些收尾工作,比如关闭数据库,关闭文件
析构函数在对象销毁的时候就会执行,当没有主动销毁对象的时候(del 对象),会默认为程序结束时,销毁对象
python会每隔一段时间来回收垃圾,什么是垃圾,当内存中的数据没有变量指向他的时候,就是垃圾,如果有指向但是没有用,也不是垃圾,也不会被销毁。
私有变量和私有函数:
私有变量只有在类内部才可以访问,私有函数也是,如何定义私有的?
只用在方法和变量的前面加上__.两个下横杠就表示这个变量或方法是私有的前面加横杠后面不用
比如如图所示:__life_value属相就是私有变量,__del__(self)就是私有方法
继承
m1=Woman("huanfeng",40)这句代码的意思就是创建一个woman的实例化对象,因为woman并没有初始化方法,所以这里使用的是是父类的初始化方法。如果子类中有初始化方法时,应该这样操作:
这个是将name还有age继续使用父类的初始化方法进行初始化,然后money使用自己的方法进行初始化,这样的好处是,在调用父类方法的时候可以在父类中获取到name和age的值,这也符合继承的思想,上面是使用父类名点__init__的方式来调用父类的初始化的方法
如果要是想要在子类方法中调用父类的方法,那么操作是父类名dian方法名,比如people.eat(self),这个self就表示m1,也就是字类的对象
在上面这个程序中有一个people类,然后有一个woman类,这个woman类继承了people类,他就拥有了父类中的一切包括初始化方法,当子类没有定义初始化方法的时候,那么初始化化子类就应该按照父类的初始化的规则来初始化,格式是class Woman(people)这句代码就表示woman继承了people
在python中最顶层的那个类是object,所以上面的定义类的方式经典类,还有一种类的定义方式是新式类。
在定义类的时候括号内部写一个object就表示当前的类的父类为object
调用新式类,父类中的初始化方法,通过super的方式,这个super表示的是class Man()括号中的内容,也就是people
python是可以多继承的,比如:
在括号中写了两个类,就表示women类继承people和relation这两个类,继承的先后顺序是有区别的,当我们调用方法的时候,如果第一个继承的找不到,才会去第二个中找,也就是第二个优先级比第一个优先级低,也就是说只要在第一个类中找到调用的那个方法,即使参数个数不匹配也不会调用第二个父类中的,此时会报错。这就是super的作用,它的作用就是先去第一个父类中找,找到就执行就算报错也执行,找不到才去下一个父类中找
同理构造方法也一样,当我们创建一个对象的时候,如果第一个类的构造方法匹配不上,第二个父类的构造方法不会根本匹配,而是直接会报错
当是这样一种继承关系的时候,调用一个方法,当d中没有这个方法的时候会先去b中找,b中找不到才回去c中找
当是这样一种继承关系的时候,调用一个方法,当d中没有这个方法的时候会先去b中找,b中找不到才回去c中找,若c中也找不到则回去A中找,以上的这种运行方式可以叫做广度优先,这是在python3中的,无论是使用新式类还是经典类
而在python2中新式类是按照也是广度优先来继承的,而经典类是按照深度优先来继承的,就是如上所示,先找b,b找不到找a,a找不到找c
多态
python其实没有支持多态的语言,但是多态就是同一接口的不同实现,只要把握好这个思想就可以实现多态的效果
一个父类animal
两个子类,一个dog,一个cat类,这两个类都有talk的方法,如果要是想调用这个方法需要
创建一个对象然后调用talk方法,这不是多态,要想实现同一接口的不同实现那么就需要使用多态的思想
定义了一个animal_talk的方法,所有想叫的动物,只用调用这个方法,并且把自身对象传递过去,就可以运行自身的talk方法了,这就实现了同一接口(animal_talk)的不同实现(狗叫和猫叫)
其实这个接口一般不单独定义成一个方法,而是定义在父类中作为一个方法,这样通过调用父类的方法就可以了。
可以看到animal_talk方法是写在类中的方法,但是这个类中的方法和其它方法有点不一样。第一这个方法没有self参数,第二这个方法上面有@staticmethod。
被注上@staticmethod之后表示这个方法是静态的,既然是静态的方法,那么方法中就不能操作this,也就是self,所以静态方法很特殊,它的参数不会有默认的self,(也就是调用该方法的自身对象)
有了静态方法,还有类方法,使用@classmethod标注,这个方法就是类方法
类方法的特性就是只能访问这个类的类变量,而实例变量获取不到
属性方法@property:把一个方法变成一个静态属性
假如:
那么以后调用这个方法的时候,不能对象.eat()
而应该对象.eat
也就是说后面调用的时候,后面不能用括号了,既然不能有括号,那么也就是说如果这个属性方法有参数,也不能传递过去,所以属性方法不能有除了self之外的参数,因为调用的时候没有办法传递参数,所以会报错。
和@property搭配使用的还有
@静态属性名.setter
@静态属性名.deleter
这两个都要写在被@property标注的静态方法之后
d=Dog("dog")
从这个程序来看,@eat.setter的作用是为参数赋值,他有一个food参数,那么可以通过
d.eat="gouliang"
来为food参数赋值,这样当
d.eat
的时候就调用了静态属性eat,输出dog is eating gouliang
也就是说@eat.setter是帮助@peoperty来提前赋值@perperty中所用到的变量的
总结一下就是@perporty是只能输出这个变量,而@eat.setter是可以设置这个变量,那还剩一个删除
@eat.deleter的作用就是删除,它内部写上del 变量名,这样当调用它的时候,就会删除掉这个变量
那么如何才能调用它呢?
del d.eat的时候会执行它,然后@eat.deleter有代码del 变量名,这就起到了删除变量的作用
类的特殊成员方法:
__doc__是输出这个类的"""xxx"""的注释,注释一般写对该类的描述
模块就是在哪个文件目录下的哪个py文件
当我们创建一个对象的时候,会自动调用该类的构造方法,
比如:d=Dog()
这句代码会自动调用dog类的构造方法
而此时还可以对象再括号一次,d()
这个会自动调用__call__方法
首先我们必须要再类中定义__call__方法,就像是构造方法一样,必须定义出来,因为默认__call__方法不存在,只有在类中定义出来,才可以使用
它的形式如上图所示,可以接收多个参数,当d(1,2,3,name=333)的时候__call__方法会自动调用
__dict__方法,该方法有两种调用方式:
方式一:类名.__dict__
打印类中的类属性不包括实例属性,以列表形式
方式二:对象名.__dict__
打印类中的实例属性不包括类属性,以列表形式
__str__方法,当我们
print 对象名的时候输出的是当前对象的内存地址,如果我们在类中写一个__str__方法的时候,那么此时print 对象名的时候就会调用__str__方法,输出该方法的返回值