本博客所有文章仅仅是博主做笔记之用,博客内容并不详细(以后有空会修改完善),思维也有跳跃之处,想详细学习博客内容可参考文章后面的参考链接,祝学习快乐。
本节要点:
- 类的语法
- 类变量和实例变量
- 特殊方法
- 继承和多态
- 私有属性和方法
- 静态方法、类方法、属性方法
- 反射
1.语法
class ClassName(object): #定义一个类
"""docstring for ClassName"""
def __init__(self, arg): #构造函数
super(ClassName, self).__init__()
self.arg = arg
x = ClassName("yang") #生成一个对象
2. 类变量和实例变量
>>> class ClassName(object):
"""docstring for ClassName"""
age = 100 #类变量
list_1 = [] #类变量
def __init__(self, name, age):
super(ClassName, self).__init__()
self.name = name #实例变量
self.age = age
>>>
>>> x = ClassName("yang",18)
>>> x.age #实例变量会覆盖类变量
18
>>> y = ClassName('hello',10)
>>> y.age
10
>>> x.age = 17
>>> y.age
10
>>> ClassName.age #可以直接通过类调用类变量
100
>>> x.IQ #没有这个属性
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'ClassName' object has no attribute 'IQ'
>>> x.IQ = 280 #可以在类外添加新属性(动态给实例绑定一个属性)
>>> dir(x)
['IQ', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'list_1', 'name']
>>> x.IQ
280
>>> hasattr(x,'IQ')
True
>>> hasattr(y,'IQ') #给x添加的实例变量不会出现在其他对象中
False
>>> ClassName.EQ = 300 #同样可以在类外添加类变量
>>> x.EQ
300
>>> y.EQ
300
附:动态给实例绑定一个方法
from types import MethodType
class Student(object):
pass
def set_age(self,age):
self.age = age
s = Student()
s.set_age = MethodType(set_age,s) # 给实例绑定一个方法
s.set_age(18)
print(s.age)
3. 特殊方法和属性
特殊方法前后各有两个下划线
构造函数 __init__()
通过类创建对象时,自动触发执行。析构函数 __del__()
类一定有析构函数,可以自己定义,销毁对象的时候自动执行。
>>> class Test(object):
... def __init__(self):
... print('生成了一个对象。。。')
... def __del__(self):
... print('析构函数执行了。。。')
...
>>> test = Test()
生成了一个对象。。。
>>> del test
析构函数执行了。。。
3 __doc__
类的描述信息
>>> class ClassName(object):
"""docstring for ClassName""" #__doc__就是这块东西
def __init__(self, arg):
super(ClassName, self).__init__()
self.arg = arg
... ... ... ... ... ...
>>> ClassName.__doc__
'docstring for ClassName'
4 __class__和__moudle__
>>> x = ClassName('yang')
>>> x.__class__ #表示当前操作的对象的类是什么
<class '__main__.ClassName'>
>>> x.__module__ #表示当前操作的对象在哪个模块
'__main__'
5 __call__ ()
对象后面加括号,触发执行。使得对象可被调用。
>>> class ClassName(object):
"""docstring for ClassName"""
def __init__(self, arg):
super(ClassName, self).__init__()
self.arg = arg
def __call__(self):
print('执行了这里.')
>>> test = ClassName('yang')
>>> test()
执行了这里.
>>> print(callable(test))
True
6 __str__()
print(obj)的时候触发打印这个函数的返回值
>>> class ClassName(object):
"""docstring for ClassName"""
def __init__(self, arg):
super(ClassName, self).__init__()
self.arg = arg
def __str__(self):
return '自定义打印。。' #注意,这里是return,而不是print
>>> test = ClassName('yang')
>>> print(test)
自定义打印。。
7 __dict__
获取类的成员(属性和方法)或者对象的成员(只有属性)。
class Province:
country = 'China'
def __init__(self, name, count):
self.name = name
self.count = count
def func(self, *args, **kwargs):
print('func')
# 获取类的成员,即:静态字段、方法、
print(Province.__dict__)
# 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}
obj1 = Province('HeBei',10000)
print(obj1.__dict__)
# 获取 对象obj1 的成员
# 输出:{'count': 10000, 'name': 'HeBei'}
obj2 = Province('HeNan', 3888)
print(obj2.__dict__)
# 获取 对象obj2 的成员
# 输出:{'count': 3888, 'name': 'HeNan'}
8 __slots__(*待补充)
https://eastlakeside.gitbooks.io/interpy-zh/content/slots_magic/
http://wiki.jikexueyuan.com/project/start-learning-python/212.html
http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143186739713011a09b63dcbd42cc87f907a778b3ac73000
9 __len__()使得可以使用len(obj)
>>> class Student(object):
def __len__(self):
return 100
>>> a = Student()
>>> len(a)
100
4.继承和多态
继承
class Person(object): #object是所有类的基类
"""docstring for Person"""
def __init__(self, name,age):
self.__flag = False
self.name = name
self.age = age
class Student(Person):
"""docstring for Student"""
def __init__(self, name, age, ID):#重构的构造函数,继承的属性和子类新的属性都要写进去
super(Student, self).__init__(name,age) #新式类写法,将继承的属性写进去,这个函数相当于把父类的构造函数抄了一遍
self.ID = ID
def test(self):
print('go to school')
多继承
一个类还可以同时继承多个类
py2 经典类是按深度优先来继承的,新式类是按广度优先来继承的
py3 经典类和新式类都是统一按广度优先来继承的
多态
(*伪多态)
5. 私有属性和方法
在Python中,如果在变量名或函数名前加上‘_ _’,就会将这个变量或函数变为私有,在类外不可访问,对子类也不可见,子类不能继承父类的私有属性和方法。
但是,事实上,python不存在真正的私有,_ _xxx或者_ _xxx()
可以在类外加上_class_ _xxx来访问。Python解释器将私有的变量名改了一个名字来实现类外私有变量名不可见。不同解释器的改名规则可能不一样。
总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉。
>>> class Person(object):
def __init__(self, name):
self.name = name
self.__age = 18
def __test(self):
print('私有方法')
>>> class Student(Person):
pass
>>> p = Person('yang')
>>> s = Student('world')
>>> print(p.name)
yang
>>> print(s.name)
world
>>> print(p.__age)
Traceback (most recent call last):
File "test.py", line 16, in <module>
print(p.__age)
AttributeError: 'Person' object has no attribute '__age'
>>> print(s.__age)
Traceback (most recent call last):
File "test.py", line 16, in <module>
print(s.__age)
AttributeError: 'Student' object has no attribute '__age'
>>> print(p._Person__age)
18
>>> print(s._Person__age)
18
>>> p.__test()
Traceback (most recent call last):
File "test.py", line 18, in <module>
p.__test()
AttributeError: 'Person' object has no attribute '__test'
>>> s.__test()
Traceback (most recent call last):
File "test.py", line 16, in <module>
s.__test()
AttributeError: 'Student' object has no attribute '__test'
>>> p._Person__test()
私有方法
>>> s._Person__test()
私有方法
6. 静态方法、类方法、属性方法
静态方法
@staticmethod
普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的(Python本质上没有不可访问的东西,只是不能按一般的调用类方法的方式去访问而已),一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法。
静态方法有什么用呢?可以把一堆函数集中放在一块,通过类名来调用,就相当于一个工具包里面有很多的函数而已。
>>> class Dog(object):
def __init__(self,name):
self.name = name
@staticmethod #截断跟类的关系
def test(self): #这样写不能以obj.test()来访问,需要把obj当参数传进去
print(self.name)
>>> d = Dog("taidi")
>>> d.test() #这样会出错
>>> d.test(d) #手动传进来一个参数,这样就可以了。
类方法
@classmethod
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量。
class Dog(object):
n = 123
def __init__(self,name):
self.name = name
@classmethod
def test(self):
print(self.name) #访问不了
print(self.n) #没问题
d = Dog("taidi")
d.test() #错误
属性方法
@property
属性方法的作用就是通过@property把一个方法变成一个静态属性
(学习东西的时候一定要知道它的应用场景,先有需求才会有解决相应需求的方法诞生。生活上也是如此,当你有某种需要的时候,一定会有相应的产品出现的,如果没有,那恭喜你,你的机会来了。。)
关于@property的知识请移步这里,这篇教程写的非常好,从需求出发,引入@property,这样的教程才能真正学习到一些东西。
7. 反射
getattr(object, name) #name是字符串
hasattr(obj, name)
etattr(obj, name, value)
delattr(obj, name)
class Foo(object):
def __init__(self):
self.name = 'wupeiqi'
def func(self):
return 'func'
obj = Foo()
# #### 检查是否含有成员 ####
hasattr(obj, 'name') #返回True
hasattr(obj, 'func')
# #### 获取成员 ####
getattr(obj, 'name') #返回的是对象的内存地址
getattr(obj, 'func')
# #### 设置成员 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1)
# #### 删除成员 ####
delattr(obj, 'name')
delattr(obj, 'func')
参考链接:
- http://www.cnblogs.com/alex3714/articles/5188179.html
- http://www.cnblogs.com/alex3714/articles/5213184.html
- http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431864715651c99511036d884cf1b399e65ae0d27f7e000
- http://wiki.jikexueyuan.com/project/start-learning-python/212.html
- http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143186739713011a09b63dcbd42cc87f907a778b3ac73000