类的定义

构造函数

def __ini__(self, ....):
pass

析构函数

def __del__(self, ...):
pass
'''
当被python回收机制进行回收会自动调用这个函数
'''

类属性

定义类的属性

1、直接定义

class Programer:
sex = 'male'

2、构造函数时定义

'''
在构造对象时需要传值
'''

class Programer:
def __init__(self, name, age):
self.name = name
self.age = age

访问控制

严格来说python没有访问控制

class Programer:
def __init__(self, name, age, weight):
self.name = name # 可以进行公开的访问
self._age = age # 单下划线表示这个类的私有属性
self.__weight = weight # 实现了部分私有属性 类里边能访问,实例化对象后不能访问

例子

class Programer:
hobby = 'play computer'
''' 类属性 '''

def __init__(self, name, age, weight):
self.name = name
self._age = age
self.__weight = weight

def get_weight(self):
''' 方法 获取weight'''
return self.__weight

if __name__ == '__main__':
programer = Programer('Tom', 23 , 80)
print(dir(programer))

print(programer.__dict__)
'''
{'name': 'Tom', '_age': 23, '_Programer__weight': 80} 可以看到键值的情况
'''


print(programer.get_weight())
''' 80 '''
print(programer._Programer__weight)
'''
80
变向的访问类的私有属性,所以说python没有私有属性
'''

定义类方法

函数和方法

  • 函数直接调用函数名即可调用
  • 而方法一般都是和对象一起使用(从属于某个类)
    class Test:
    def test(self):
    pass
    a = Test()
    print(a.test)
    '''
    <bound method Test.test of <__main__.Test object at 0x0000000002818518>>
    '''


    a.test = '112233'
    print(a.test)
    '''
    112233
    '''

    '''
    一切皆对象
    '''

常用方法定义

class Example:
def add(self):
''' 公用方法 '''
pass
def _minus(self):
''' 私有方法 '''
pass
def __multiply(self):
pass

类装饰器



@classmethod
调用的时候用类名,而不是某个对象(不是生成对象再调用方法)

@property
像访问属性一样调用方法

@staticmethod

类方法例子

class Programer:
hobby = 'play game'

def __init__(self, name, age, weight):
self.name = name
self._age = age
self.__weight = weight

''' 类方法 '''

@classmethod
def get_hobby(cls):
return cls.hobby

''' 直接对象名+方法名,获得属性不需要加()'''

@property
def get_weight(self):
return self.__weight

# 正常的类方法
def self_introduction(self):
print('My Name is %s \nI am %s years old\n' % (self.name, self._age))


if __name__ == '__main__':
programer = Programer('Tomcat', 23, 90)
'''实例化 得到对象'''

print(dir(programer))

# 以类名调用类方法(不需要进行实例化)
print(Programer.get_hobby())
'''
play game 调用类方法
@classmethod
直接使用的是类名加方法
'''



# 以属性方式调用类方法
print(programer.get_weight)
'''
90
@property 装饰后访问此方法,和访问属性一样,不需要加括号
'''


programer.self_introduction()
'''
My Name is Tomcat
I am 23 years old
正常的调用类方法的方式
'''

类的继承

语法:

class B(A):
<语句块>
.
.


super()
调用父类方法
class A:
def method(self, arg):
pass
class B(A):
def method(self, arg):
super(B, self).method(arg)
'''
调用父类的方法
第一个参数 自己的类名
第二个参数是 self
. 连接是调用父类的方法名
最后是传入的参数
'''

子类的类型判断

  • isinstance
  • issubclass

多继承

_例子_

class Programer:
hobby = 'play game'

def __init__(self, name, age, weight):
self.name = name
self._age = age
self.__weight = weight

''' 类方法 '''

@classmethod
def get_hobby(cls):
return cls.hobby

''' 直接对象名+方法名,获得属性不需要加()'''

@property
def get_weight(self):
return self.__weight

# 正常的类方法
def self_introduction(self):
print('My Name is %s \nI am %s years old\n' % (self.name, self._age))

class BackendProgramer(Programer):
def __init__(self, name, age, weight, language):
super(BackendProgramer, self).__init__(name, age, weight)
self.language = language
''' 调用父类以后 多出的属性进行赋值'''

if __name__ == '__main__':
programer = BackendProgramer('Tomcat', 23, 90, 'Python')
'''实例化 得到对象'''

print(dir(programer))

print(programer.__dict__)
''' {'name': 'Tomcat', '_age': 23, '_Programer__weight': 90, 'language': 'Python'}
三个属性是从父类继承
'''

print(type(programer))
''' <class '__main__.BackendProgramer'> '''

print(isinstance(programer, Programer))
'''
True
判断这个类的父类是否是Programer
'''

类的多态

  • 继承
  • 方法重写
    class Programer:
    hobby = 'play game'

    def __init__(self, name, age, weight):
    self.name = name
    self._age = age
    self.__weight = weight

    ''' 类方法 '''

    @classmethod
    def get_hobby(cls):
    return cls.hobby

    ''' 直接对象名+方法名,获得属性不需要加()'''

    @property
    def get_weight(self):
    return self.__weight

    # 正常的类方法
    def self_introduction(self):
    print('My Name is %s \nI am %s years old\n' % (self.name, self._age))

    class BackendProgramer(Programer):
    def __init__(self, name, age, weight, language):
    super(BackendProgramer, self).__init__(name, age, weight)
    self.language = language
    ''' 调用父类以后 多出的属性进行赋值'''

    ''' 方法重写 '''
    def self_introduction(self):
    print('My Name is %s \nMy favourite language is %s .\n' % (self.name, self.language))

    def introduce(programer):
    if isinstance(programer, Programer):
    programer.self_introduction()

    if __name__ == '__main__':
    programer = Programer('Tomcat', 23, 90, )
    '''实例化 得到对象'''
    backend_programer = BackendProgramer('nginx', 20, 85, 'Python')

    introduce(programer)
    '''
    My Name is Tomcat
    I am 23 years old
    '''

    introduce(backend_programer)
    '''
    My Name is nginx
    My favourite language is Python .
    '''

    # 特点
    '''
    添加功能的时候非常的简单,只要判断是不是属于父类,
    不管传进来的是哪个子类,都可以调用期方法
    '''

类的魔术方法

方法名的前后有两个下划线
def init(self):
pass

['_Programer__weight', '__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', 'get_hobby', 'get_weight', 'hobby', 'name', 'self_introduction']

类的实例化过程

  • 创建类的对象
  • 类的初始化

init 之前会调用new来返回一个类的初始对象
如果有需求可以重写new 方法

def __new__(cls): --->> def __init__(slef):

例子

class Programer(object):
def __new__(cls, *args, **kwargs):
print('call __new__ method')
print(args)
return super(Programer, cls).__new__(cls, *args, **kwargs)
def __init__(self, name, age):
print('call __init__ method')
self.name = name
self.age = age

if __name__ == "__main__":
programer = Programer('Nginx', 2007)
print(programer.__dict__)

'''
call __new__ method
('Nginx', 2007)

call __init__ method
{'age': 2007, 'name': 'Nginx'}

印证了 __new__ 构造方法__init__时先调用new在返回对象交给init放进行初始化
'''

销毁对象

del()
垃圾回收时会自动进行调用(少用)

类与运算符

s = 'test'
print(s == s) # True

print(dir(s))
'''
['__add__',
'__eq__','__ge__', '__gt__',
'__ne__','__le__', '__lt__',
...
]
# 从此例子说明如果类需要某些魔术方法则需要自己加入魔术方法
'''

运算符分类

  • 比较运算符


    __cmp__(self, other): 包含了以下的情况 >,< ,>=, <=
    __eq__(self, other):
    __lt__(self, other):
    __gt__(self, other):
  • 数字运算符

    def __add__(self, other): +
    def __sub__(self, other): -
    def __mul__(self, other): *
    def __divmod__(self, other): /
  • 逻辑运算符

    def __or__(self, other):
    def __and__(self, other):

例子

class Programer:
hobby = 'play game'

def __init__(self, name, age, weight):
self.__weight = weight
self.name = name
if isinstance(age, int):
self.age = age
else:
raise Exception('age must be int')

def __eq__(self, other):
if isinstance(other, Programer):
if self.age == other.age:
return True
else:
return False
else:
raise Exception('The type of object must be Programer')

def __add__(self, other):
if isinstance(other, Programer):
return self.age + other.age
else:
raise Exception('The type of object must be Programer')
''' 类方法 '''

if __name__ == '__main__':
p1 = Programer('Tomcat', 23, 90, )
p2 = Programer('nginx', 21, 90, )
print(p1==p2)
print(p1+p2)

'''
False
44
'''

类的展现

有时候类实例化以后可以使用print打印出来

转换为字符串

str 把对象转换为较适合人看的字符串
repr 把对象转换为适合机器看的字符串
unicode

eval() 可以把python一段字符串当做代码来运行(repr可以可转换, 而str不行)

展现对象的属性

dir()
dir() 魔术方法来控制dir展示的结果

例子

class Programer:
hobby = 'play game'

def __init__(self, name, age):
self.name = name
if isinstance(age, int):
self.age = age
else:
raise Exception('age must be int')

''' 注释一下代码'''
def __str__(self):
return '%s is %s years old' % (self.name, self.age)
def __dir__(self):
# 只返回属性的键
return self.__dict__.keys()

if __name__ == '__main__':
p = Programer('Tomcat', 23)
print(p)
print(dir(p))

'''
注释前:
<__main__.Programer object at 0x00000000021F8550>

['__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', 'hobby', 'name']

'''


'''
注释后:
Tomcat is 23 years old

['age', 'name']
'''

类的属性访问控制

设置对象属性

  • setattr
class A:
# 方法1
def __setattr__(self, key, value):
setattr(self, key, value)
'''
如果在给一个对象设置属性的时候,
他实际上会调用到这个魔术方法,
默认情况下不需要进行定义(父类继承)
'''

# 这种方法不要使用 容易引起无限递归调用 setattr调用内建的__seatter__
# 方法2 建议这种方法
def __setattr__(self, key, value):
self.__dict__[key] = value

查询对象的属性

class A:
def __getattr__(self, item):
pass
def __getattribute__(self, item):
pass

'''
第一个方法:
访问这个属性,在默认情况下,没有被查询到的情况下调用它
第二个方法:
访问属性方法,每次都会调用到(使用这种方法不容易引起无限递归调用)
'''

删除对象属性

del时会调用

class A:
def __delattr__(self, item):

例子

class Programer:
hobby = 'play game'

def __init__(self, name, age):
self.name = name
self.age = age
def __getattribute__(self, item):
# return getattr(self, item) # 错误写法
''' RecursionError: maximum recursion depth exceeded '''

# return self.__dict__[name] # 错误的写法
'''
[Previous line repeated 326 more times]
RecursionError: maximum recursion depth exceeded
'''


return super(Programer, self).__getattribute__(item)

def __setattr__(self, key, value):
# setattr(self, key, value) # 错误的写法
''' RecursionError: maximum recursion depth exceeded 返回递归深度限制错误 '''

self.__dict__[key] = value

if __name__ == '__main__':
p = Programer('Tomcat', 23)
print(p.name)