python 面向对象编程
1. 类的 __new__() 方法
定义一个类时,可以用__init__函数来设置类具有的属性,但实际上最先执行的是 __new__ 函数,通过该函数,返回一个
类的实例,这也是为什么init函数有self参数的原因。
class Animal(object):
def __new__(cls,*args,**kw):
return Animal.__new__(cls,*args,**kw)
2. 类的 __del__方法
在该对象被销毁时自动调用__del__方法,可重写print试试。但是实际上,用cmd和sublime,pycharm编译器执行脚本时,并非
销毁对象时执行__del__,而是在实例化对象时执行的;只有在python自带的IDE中才会在销毁对象时执行,我也不知道为什么。
3. 公有和私有属性,方法
python 的类中,如果有一些属性不想给外部权限来访问或者修改,可以在属性或者方法的名字前加俩下划线__,声明为
私有属性。则在外部调用该属性时返回ValueError.
class girl(object)
def __init__(self,name,phone):
self.name = name
self.__phone = phone
Mary = girl("马力",110)
使用场景:如果想只给外部访问的权限,不给修改的权限。可以在类里头定义一个 返回 属性的函数class girl(object)
def __init__(self,name,phone):
self.name = name
self.__phone = phone
def want_her_phone(self):
print(self.__phone)
Mary = girl("马力",110)
Mary.want_her_phone() >> 110
使用场景2:给与外部访问与修改权限,但修改值应按照设计的范围来。
class girl(object):
def __init__(self,name):
self.name = name
self.__phone = 12312312312
def want_her_phone(self):
print(self.__phone)
return self.__phone
def change_phone(self,new):
if len(str(new)) != 11 or str(new)[:3] not in ['153','138','157','183']:
raise ValueError('you cheat me!')
self.__phone = new
Mary = girl("玛丽")
Mary.change_phone(15734567654) >> 修改phone 属性
另外:实际上私有变量的工作原理是将变量名改为: _类名__变量名,仍可以通过这个来调用。class girl(object)
def __init__(self,name,phone):
self.name = name
self.__phone = phone
Mary = girl("马力",110)
print(Mary._girl__phone)
在属性名前只加一个下划线 _ 也算私有属性,但仍然能访问和修改,但尽量别改。
4. 注解 @property
从上几个例子可以看出,想要对对象的属性值设定一定的范围,就得用到函数,修改时要 obj.method(),代码很长很不爽,此时
使用装饰器@property可以让你直接跟用属性一样,直接点 . obj.attr = x。
语法是:先定义两个函数,函数名为属性名,第一个函数返回属性值,第二个函数修改属性值。然后在第一个函数头上写个
@property, 在第二个函数头上写个 @属性名.setter就行
class girl(object):
def __init__(self):
self.__age = 30
@property
def age(self):
return self.__age
@age.setter
def age(self,value):
if not isinstance(value,int):
raise ValueError('must be int!')
if value > 28 or value < 18:
raise ValueError("Is it not pretty enough for you?")
self._age = value
a = girl()
a.age = 35 # 不符合范围,报错
print(a.age)
5. 类的打印信息
如果类直接打印 print(girl()) 会出现一个内存地址,不仅没用而且让人看起来很迷惑。我们可以使用 __str__函数来修改
类的打印信息,打印出我们想让它显示的内容。
class girl(object):
def __str__(self):
return "这是一个类"
print(girl()) >>这是一个类
6. 引用统计
先引入sys模块,import sys。然后sys.getrefcount(obj),返回被引用的次数。
import sys
print(sys.getrefcount(int))>>69次sys模块里
7. 类方法,静态方法
@staticmethod
通常情况下,在类中定义的所有函数都是对象的绑定方法,对象在调用绑定方法时会自动将自己作为
参数传递给方法的第一个参数。但是静态方法就不会把自己传进去,相当于一个全局函数样的:
class A(object):
@staticmethod
def fn1():
print("haha")
A.fn1() >> haha
a = A()
a.fn1() >> haha
@classmethod
与实例方法相似,只不过首个参数会自动接收类对象,类对象可以调用。但实际上,实例对象也能用,
会把自己的父类传入第一个参数。
class A(object):
@classmethod
def fn2(cls,a,b): # cls跟self一样,只是为了语义化,可以用任意的字符
print(cls,a,b)
A.fn2(1,2) >><class '__main__.A'> 1 2
a = A()
a.fn2(3,4) >><class '__main__.A'> 3 4
另外,类中定义的实例方法,即正常定义的方法,类对象也能调用,只不过会当成一个普通函数,第一个参数并不会自动
接收实例对象,包括self,定义了几个参数,就要给几个参数。
class A(object):
def fn3(self,a,b):
print(self,a,b)
A.fn3(1,2,3) >> 1,2,3
a = A()
a.fn3(123,12) >>
<__main__.A object at 0x007306F0> 123 12
4 三个特性面对对象的三个特性为: 封装,继承,多态。
封装: 应该注意到了,类的定义格式很像函数,将一大堆代码写在类的肚子里,如果有多个对象很多特征相似,可以
把这些特征封装进一个类中。
继承: 类有继承的功能,所谓继承就是从一个类里头实例化一个对象,你没写这个对象的属性方法,这个对象从他的类中
得到了所有的属性方法,可以直接调用。
class dog(object):
def __init__(self)
self.leg = 4
def attack_method(self):
print("the dog is bitting!")
gou = dog() # 实例对象gou 从类 dog 中继承了所有的属性和方法
gou.leg >> 4
gou.attack_method() >> the dog is bitting!
类也能继承,一个类定义的时候,括号中有个object参数,表示从 python 自带的object类中继承相应的属性以及方法。
同样的,也能从其他类中继承属性和方法
class animal(object):
def __init__(self):
self.look = "cute"
class dog(animal):
def looklike(self):
print(self.look)
# 调用了未定义的 look 属性
gou = dog()
gou.looklike() >> cute
gou.look >> cute # dog中未定义的属性
多重继承,有时候一个对象不仅有这个类的特性,还有那个类的特性,此时可以可以定义一个类,继承多个类。
class animal(object):
def __init__(self,color):
self.color = color
class dog(object):
def __init__(self,name):
self.name = name
def wang(self):
print("汪!")
class village_dog(animal, dog):
pass # 从animal和dog中继承
gou = village_dog("黄色")
gou.color >> "黄色"
gou.wang() >> "汪!"
# 要注意的是,animal和dog中都有 init 函数,init函数只会执行一个,就近选择,如果自身有用自己的,自己没,用参数里靠前的那个类的
多态:多态这个特性是理所当然的,A类继承自B类,B类有继承自C类,C类甚至继承自D和E类。则从A类实例化后的对象,
判断类型时,可以是 A,B,C,D,E 类,针对这些类定义的函数他都能用,这就是多态。
class animal(object):
def __init__(self,color):
self.color = color
class dog(object):
def __init__(self,name):
self.name = name
def wang(self):
print("汪!")
class village_dog(animal, dog):
pass # 从animal和dog中继承
gou = village_dog("sdfa")
isinstance(gou,dog) >> True
isinstance(gou,animal) >> True
# isinstan 判断是否为XX类型 如果用type 则只显示 village 类
4.实例属性和类属性
实例属性就是__init__绑定的那些属性,类属性是在类里头直接写:attr = value,就设置了一个类属性。
但是实例会继承类的这个属性,实例重写时覆盖。
5 类的一些操作方法