类大致分为两块区域:如下图
# 每个区域详细划分:
class A:
name = 'Agoni' # 静态变量
_password = '123456xxx' # 私有静态变量
def __init__(self,name,age):
self.name = name # 对象属性
self.__age = age # 私有静态属性
def fucn1(self): # 普通方法
pass
def __func(self): # 私有方法
pass
@classmethod # 类方法
def classs_func(cls): # 定义类方法,至少有一个cls参数
print('类方法')
@staticmethod # 静态方法
def static_func(): # 定义静态方法,无默认参数
print('静态方法')
@property # 属性
def prop(self):
pass
# 所有的私有成员,只能在类内部使用,不能在类的外部以及派生类中使用
# 公有成员在类的任何地方都能访问
方法包括:普通方法,静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同.
实例方法:
- 定义:第一个参数必须是实例对象,该参数名一般约定为 'self' ,通过它来传递实例的属性和方法(也可以传递类的属性和方法)
- 调用:只能由实例对象调用
类方法:
- 定义:使用装饰器@classmethod 第一个参数必须是当前类对象,该参数名一般约定为 ' cls ',通过它来传递类的属性和方法(不能传实例的属性和方法)
- 调用: 实例对象和类都可以调用
静态方法
- 定义:使用装饰器@staticmethod 参数随意,没有 self cls 参数,但是方法体重不能使用类和实例的任何属性和方法.
- 调用: 实例对象和类对象都可以调用
双下方法:(后面会讲到)
-
定义: 双下方法是特殊方法,世界时期提供的由双下划线加方法名加双下划线
__方法名__
的具有特殊意义的方法,双下方法主要是Python源码程序员使用的.我们在开发中尽量不要使用双下划线方法.深入研究双下划线方法,有助于阅读源码
-
调用:不同的双下方法有不同的出发方式.
7.5.1 类方法
# 类方法举例说明
class A:
num = 1
def func(self):
print('实例方法')
@classmethod # 类方法: 由类名直接调用的方法,自动将类名传给 cls
def c__func(cls):
print('类方法')
print(cls.num) # 通过类查看类中的属性
o = cls() # cls是A类,类名加括号实例化A
obj = A()
A.func(obj) # 通过类名调用类中的实例方法,要给self传参数
A.c_func() # 通过类名调用类中的类方法
obj.c_func() # 对象也可以调用类的方法,但是会自动将类名传给cls
# 例题 定义一个学生类,统计学生的个数
class Student:
num = 0
def __init__(self,name):
self.name = name
self.count()
@classmethod
def count(cls):
cls.num += 1
@classmethod
def addNum(cls):
return cls.num
s1 = Student('alex')
s2 = Student('alex')
s3 = Student('alex')
print(Student.addNum())
7.5.2 静态方法
# 静态方法:不依赖与类和对象,就是一个普通的函数 类名和对象都可以调用,不需要传参
class A:
def func(self):
print(111)
@classmethod
def a_func(cls):
pass
@staticmethod
def s_func():
print('静态方法')
A.s_func()
obj = A()
obj.s_func()
# 举例
import time
class TimeTest:
def __init__(self,hour,minute,second):
self.hour = hour
self.minute = minute
self.second = second
def func(self):
pass
@staticmethod
def show_time():
return time.strftime("%H:%M:%S",time.localtime())
print(TimeTest.show_time())
obj = TimeTest(1,20,30)
obj.showTime()
7.5.3 属性
以bmi为例,测定人体体脂
class Bmi:
def __init__(self,name,height,weight):
self.name = name
self.height = heiget
self.weight = weight
@property
def bim(self):
return self.weight/self.height**2
b = Bim('Agoni',1.75,65)
print(b.bim) # 调用属性时,不需要加()
为什么要用property
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
class Foo:
def __init__(self,name):
self.name = name
@property
def aaa(self):
print('get的时候运行我')
@aaa.setter
def aaa(self,v):
print(v) # 123
print('修改的时候运行我')
@aaa.deleter
def aaa(self):
print('删除的时候运行我')
obj = Fpp('Agoni')
obj.aaa # get的时候运行我
obj.aaa = '123' # 修改的时候运行我
print(Foo.aaa) # <property object at 0x00000137E3C578B8>
del obj.aaa # 删除的时候运行我
# 设置属性的另一种写法
class Foo:
def get_aaa(self):
print('get的时候运行我啊')
def set_AAA(self,value):
print('set的时候运行我啊')
def delete_AAA(self):
print('delete的时候运行我啊')
bbb = property(get_aaa,set_aaa,delete_aaa) # 内置property三个参数与get,set,delete一一对应
f1 = Foo()
f1.bbb
f1.bbb = 'aaa'
def f1.bbb
7.5.4 isinstace与issubclass
isinstace(obj,N) 判断obj对象是由N类(N类的派生类)实例化的对象,返回True
class A:
pass
class B(A):
pass
class C(B):
pass
obj = B()
print(isinstance(obj,B)) # True
print(isinstance(obj,A)) # True
print(isinstance(obj,C)) # False
issubclass(M,N) 判断M类是N类的子孙类
class A:
pass
class B(A):
pass
class C(B):
pass
print(issubclass(C, B)) # True
print(issubclass(C, A)) # True
7.5.5 type 元类
type到底是什么?
type元类,Python中一切皆对象,一个类也是一个对象.name这个(类)对象肯定是由类实例化出来的,Python中自己创建的所有类,以及大部分 list str 等这些类,都是从type元类实例化得来的 .
Python中继承object类都是新式类
object也是有type元类实例化得来的
s = 'affjkl'
l = [1,2,3]
print(type(s)) # 判断的是对象从属于哪个类
print(type(l))
<class 'str'>
<class 'list'>
class A:
pass
print(type(A)) # <class 'type'>
from collections import Iterable
from collections import Iterator
print("__init__" in dir(s)) True
print(isinstance(s,Iterable)) True