Python基础之六——类

本博客所有文章仅仅是博主做笔记之用,博客内容并不详细(以后有空会修改完善),思维也有跳跃之处,想详细学习博客内容可参考文章后面的参考链接,祝学习快乐。

本节要点:

  1. 类的语法
  2. 类变量和实例变量
  3. 特殊方法
  4. 继承和多态
  5. 私有属性和方法
  6. 静态方法、类方法、属性方法
  7. 反射

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. 特殊方法和属性

特殊方法前后各有两个下划线

  1. 构造函数 __init__()
    通过类创建对象时,自动触发执行。

  2. 析构函数 __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')

参考链接:

  1. http://www.cnblogs.com/alex3714/articles/5188179.html
  2. http://www.cnblogs.com/alex3714/articles/5213184.html
  3. http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431864715651c99511036d884cf1b399e65ae0d27f7e000
  4. http://wiki.jikexueyuan.com/project/start-learning-python/212.html
  5. http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143186739713011a09b63dcbd42cc87f907a778b3ac73000
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值