def 函数名(参数): pass class 类名: def 函数名(self,参数): # self必填 pass z1 = 类名() # 这时,调用对象 z1,self参数即为 z1
例1:python
class bar: def foo(self,arg): print(self,arg) z1 = bar() print(z1) # <__main__.bar object at 0x0000019BC3088D30> z1.foo('wjz') # <__main__.bar object at 0x0000019BC3088D30> wjz z2 = bar() print(z2) # <__main__.bar object at 0x0000019BC306B358> z2.foo('wjk') # <__main__.bar object at 0x0000019BC306B358> wjk
从上面的例子能够看出,self 就是当前调用的对象(即便后面继承时);web
例2:数据库
class bar: def foo(self,arg): print(self.job,arg) z1 = bar() z1.job = 'IT' z1.foo('wjz') # IT wjz z2 = bar() z2.job = 'IT' z2.foo('wjk') # IT wjk
从上面能够看出,当向对象存储变量时,它会把该变量传给类里面的方法;编程
构造方法:函数式编程
当 obj = 类名() 时,其实是作了两件事: 在内存中开辟空间,建立对象; 经过对象,自动执行了一个方法:__init__方法(别名:构造方法)。
把公用的变量封装到init方法中。 例如:函数
class DataBaseHelper: def __init__(self,ip,port,username,password): self.ip = ip self.port = port self.username = username self.password = password def insert(self): pass def delete(self): pass def update(self): pass def select(self): pass
适用场景:若是多个函数都用一些共同参数,则适合面向对象来作。例如上面数据库操做;spa
举例:指针
class f: def f1(self): print("in the f.f1") class s(f): #这里加一个括号,指明该类的父类(基类);子类(派生类)会继承父类的方法;s类中找不到发方法,会去f类中找。 def s1(self): print("in the s.s1") def f1(self): super(s,self).f1() # 这里super(s,self) 表示是s的父类; f.f1(self) # 这个等效上面这句 super(s,self).f1();注意,必定不能忘记self print("in the s.f1") z = s() z.f1()
多继承: 若是子类继承多个父类,则排在前面的父类优先;如:code
class father1: def a1(self): print("in the f1.a1") class father2: def a1(self): print("in the f2.a1") class son(father1,father2): # father1在前面,优先继承; def s1(self): print("in the son.s1") z = son() z.a1() # 等效 son.a1(z) 打印 in the f1.ar 此时,father1和father2都有a1方法,而且son的父类有两个,则按顺序优先。
上面例子中,假如father1中没有a1方法,而father2有。可是father1的父类有a1,则继续在father1的父类中查找。都没有时,才会去father2。可是,若是father0是father1和father2共同的父类,则会最后继承共同的父类。如图:对象
python中,原生多态。这个不重要,先忽略吧。
类(class)的成员有字段、方法;其实还有一个属性
在类中定义的变量,称为静态字段,属于类,保存在类中,能够经过类或者对象访问;
在类中的方法中定义的字段,称为普通字段,属于对象,保存在对象中,只能经过对象访问;
以下:
class make: port = 22 # 静态字段 def __init__(self,ip,username,passwd): self.ip = ip # 普通字段 self.username = username self.passwd = passwd z1 = make('1.1.1.1','root','123456') print(z1.ip,z1.username,z1.passwd,z1.port) # 打印 1.1.1.1 root 123456 22 z2 = make('2.2.2.2','admin','admin') print(z2.ip,z2.username,z2.passwd,z2.port) # 打印 2.2.2.2 admin admin 22 print(make.port) # 打印 22 可见,静态字段属于类,同时也能够经过类对应的对象取得(由于对象经过类对象指针指向该类)。
构造方法:在上面面向对象三大特性之封装章节已经提到,即init方法;self是必须的;
普通方法:和构造方法同样,只是名字不是 init的方法就是普通方法;由对象调用,也能够经过类进行调用(必须指定self对象),self是必须的;
静态方法:在普通方法前面加上装饰器 staticmethod,便是静态方法;可是有个区别:self不是必须的;普通方法调用时,self就是当前调用对象;而静态方法中,若是指定了self,则必须指定self才能够;由类或对象(对象调用实际上是根据类对象指针,经过类进行调用)调用;
类方法:在普通方法前面加上装饰器 classmethod,便是类方法;类方法中,通常不使用self,而是写成 cls,cls为当前类;由类直接调用;类方法和静态方法没有太大区别;
例如:
class make: def __init__(self): # 构造方法 pass def upload(self): # 普通方法 pass @staticmethod def status(self): # 静态方法,self不是必须的,能够不要self; pass @classmethod def classmd(cls): # 类方法,这里通常写cls print(cls) pass make.classmd() # 打印结果和 print(make)同样。
说类的成员有两种。其实还有一种,定义像方法,调用像字段;咱们叫它 属性
这种属性还能够修改、删除;其实并非真的删除,只是伪造字段的操做(修改、删除)
class make: @property def its(self): # 定义属性,若是定义了property以后,后面还有getter,则优先执行getter;若是没有定义getter,则调用时执行property print("property") return 1 @its.getter def its(self): # 优先级高于property; print("getter") @its.setter def its(self,value): # 定义属性its能够修改 print(value,"setter") @its.deleter def its(self): # 定义属性its能够删除 print("delete") obj = make() r = obj.its # obj.its像是调用字段,可是its定义时像方法; print(r) # 返回 1 obj.its = 123456 # 看似是更改,实际上是找到 its.setter,而后执行。123456当作参数传给 its.setter del obj.its # 看似是删除,实际上是找到its.deleter,而后执行
在上面的基础上补充:
class make: @property def f1(self): print("in the f1") return 123 @f1.getter def f1get(self): print("in the f1getter") return 00 @f1.setter def f1set(self,value): print("in the f1setter",value) return 11 @f1.deleter def f1del(self): print("in the f1deleter") return 22 @f1get.fget # 这里能够执行 @property修饰的方法f1; def f2(self): print("in the f2") return 456 @f1set.fset def f3(self): print("in the f3") return 789 @f1del.fdel def f4(self): print("in the f4") return 000
咱们不调用类,只是定义这个类,这时:
@f1get.fget 会自动执行 f1get方法;
@f1set.fset 会自动执行 f1set方法;
@f1del.fdel 会自动执行 f1del方法;
三个是相同的原理,注意:fget能够执行 property、getter的对象;fset只能够执行setter的对象;fdel只能够执行deleter的对象。
这里就拿fget举例:
另外:
def f1(self): return 123 per = property(fget=f1) ------ 上下两部分等效 ------ @property def per(self): return 123
同理,
class make: def f1(self): print("in f1") return 123 def f2(self,val): print("in f2",val) return 456 per = property(fget=f1,fset=f2) # 这里就是关键字参数,fget/fset能够省略,就是位置参数;即,fget、fset、fdel顺序。property(fget,fset,fdel,doc="描述") z = make() z.f1 = 123 ------ 上下两部分等效 ------ class make: @property def f1(self): print("in f1") return 123 @f1.setter def f1(self,val): print("in f2",val) return 456 z = make() z.f1 = 123