面向对象-内置函数和内置方法

python内置函数

isinstance(obj,class)   

判断一个对象是否是已知的类型,类似type()

isinstance语法:isinstance(object,classinfo)

  • object 是实例/对象
  • classinfo 可以是直接或间接类名,基本类型或者由他们组成的元组

返回值

如果对象的类型与classinfo相同,返回bool值True,否则返回False

 

isinstance 与type的区别:

  • type()不会认为子类是一种父类类型,不考虑继承关系
  • isinstance() 会认为子类是一种父类类型,考虑继承关系,

如果要判断两个类型是否相同的时候尽量用isinstance()

示例1:

a = [1,2,3] print(isinstance(a,list))
输出: True


示例2:

class
A(object):pass class B(A):pass b=A() print(isinstance(b,A)) # 返回True b 是 A 的对象 print(type(b) is B) # 返回False b不是B类的对象 print(type(b) is A) #type 在这里是检测对象是不是类的对象/实例

issubclass( ) 

  判断两个类是否有继承关系,,如果真的有继承关系,那就返回bool值True/False

 

class A(object):pass
class B(A):pass
print(issubclass(B,A))  # True  B类是A类的子类
print(issubclass(A,B))  # False

内置方法

什么是内置方法?

内置方法也叫双下方法,魔术方法,它们在python中处处皆是,它们是一些可以让你对类添加"魔法"的特殊方法,经常都是双下划线包围来命名的比如(__init__,__str__)等等,到现在还是没有很好的办法来解释它们.

内置方法的特点

一定有某一个语法或者一种写法自动触发这个方法.

常见常用的内置方法

最常见的__init__ 是个初始化方法,类的初始化方法, 然而当我们执行 a =class()的时候,__init__并不是 第一个被调用的方法,事实上__new__第一个被调用,这个方法才真正的创建了实例/对象,当这个对象生命周期结束的时候,这时候__del__方法会被调用.看到这样的联系,让我们进一步了解他们的特性!

__new__  也叫构造方法,__(cls,[...)__  它提供了一个实例化对象的时候所需要的内存空间 例如--->创建空间

首先说说设计模式中的单例模式,  __new__是对象实例化的时候第一个被调用的方法,它只取cls也就是类的参数,把其他参数传给__init__..

单例模式示例1

class Teacher2:
    flag = None  #静态属性为空
    def __new__(cls, *args, **kwargs):
        if cls.flag is None:  #执行判断 cls.flag 也就是Teacher2类的静态属性为空的情况下
            cls.flag = object.__new__(cls)   #这句话直走一次
            #Teacher2继承的父类 object.__new__(cls)开辟/构建的空间地址赋予Teacher2类的静态属性
            print(cls.flag)
        return cls.flag   #类的静态属性得到的空间地址赋值Sheldon2

Sheldon2 = Teacher2()
ssa = Teacher2()  #当ssa执行实例化的时候,flag 已经不等于None,而等于一个空间地址, 不走if判断,直接把原先的空间地址赋值给ssa

单例模式示例2

class Teacher:
    flag = None
    def __new__(cls,*args,**kwargs):  #
        if cls.flag is None:
            cls.flag = object.__new__(cls)
        return cls.flag
    
    def __init__(self,name):
        self.name = name

Sheldon = Teacher('Sheldon')
Penny = Teacher('Penny')
print('Sheldon.name')   #输出  Sheldon
print('Penny.name')    #输出  Penny
print('Sheldon.name')  ##输出  Penny

__init__   (self[...)  类初始化方法  实例化

它获取任何传给构造器的参数,(例如Sheldon = Teacher('Sheldon')  __init__ 就会接收到参数Sheldon.  __init__在python类的定义中用的最多

__del__ (self)  析构方法

__del__ 是对象的销毁器,它并不是实现了语句中 del Sheldon 因此它并不等于 Sheldon.__del__(), 而是定义了对象的垃圾回收时的行为,当对象需要销毁时做的一些处理的时候,这个方法会用到,

class Teacher:
    def __init__(self,name):
        self.name = name
    def __del__(self):
        print('执行删除动作')

Sheldon = Teacher('Sheldon')
print('11111')
# 输出顺序 11111 ---> 执行删除动作 ---> 删除Sheldon
del Sheldon  #  执行del 对象的时候触发了__del__ ,在真正删除Sheldon对象前,执行方法__del__
            # 如果我们不删除 Sheldon ,那么程序的执行过程中或最后,垃圾回收机制会替你执行del Sheldon
            # del Sheldon ---> 执行__del--->删除Sheldon

__call__(self[args...)  可调用的对象

你可能已经知道了,在Python中,函数是一等的对象。这意味着它们可以像其他任何对象一样被传递到函数和方法中,这是一个十分强大的特性。

允许类的一个实例像函数那样被调用。本质上这代表了 a() 和 a.__call__() 是相同的。注意 __call__ 可以有多个参数,这代表你可以像定义其他任何函数一样,定义 __call__ ,喜欢用多少参数就用多少。

class Student:
    def __init__(self,name,sex):
        self.name = name
        self.sex =sex
    def __call__(self, *args, **kwargs):
        print('执行调用了')
Sheldon = Student('Sheldon','male')
# callable() 查看某个变量是否能被调用
#callable(变量) 返回True 意味着 变量()--->调用
print(callable(Student))  #类可以被调用
print(callable(Sheldon))  # 对象可以被调用
Sheldon()  #执行__call__方法 
View Code

 __str__ (self) 定义类的实例调用str()的行为

能在打印对象的时,不输出无用的内存地址,输出你需要的格式化字符串

常用写法: 1.  print(对象)    2.str(对象)  3.'%s'%对象

class Course:
    def __init__(self,name,price,period,teacher):
        self.name = name
        self.price = price
        self.period = period
        self.teacher = teacher

    def __str__(self):  #必须有一个返回值,必须返回一个str类型
        return '%s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher)
course_lst = []
python = Course('python',1111,'12','Sheldon')
linux = Course('linux',2222,'12','Lins')
print(python)   # 写法1
print(str(python)) # 写法2
print('课程展示 : %s'%python)  # 写法3
course_lst.append(python)
course_lst.append(linux)
for course in course_lst:
    print(course)   # 直接展示所有课程

__repr__ (self)    是__str__(self) 的备胎,(有str就调用str,没有str调用repr)

定义对类的实例调用repr()时的行为,str()和repr()最大的区别在于'目标用户',repr()的作用是产生机器可读的输出,(大部分情况下,输出可作为python有效代码),而str()则产生人类可读输出

示例1

class Course:
    def __init__(self,name,price,period,teacher):
        self.name = name
        self.price = price
        self.period = period
        self.teacher = teacher
    def __repr__(self): # 必须有返回值,必须返回一个str类型
        return 'repr --> : %s,%s,%s,%s' % (self.name, self.price, self.period, self.teacher)

python = Course('python',1111,'12','Sheldon')
linux = Course('linux',2222,'12','Lins')
print('%r'%python)
print('%s'%python)
print(str(python))
print(repr(python))
#全部输出  repr可以输出str方法
repr --> : python,1111,12,Sheldon
repr --> : python,1111,12,Sheldon
repr --> : python,1111,12,Sheldon
repr --> : python,1111,12,Sheldon

示例2

class Course:
    def __init__(self,name,price,period,teacher):
        self.name = name
        self.price = price
        self.period = period
        self.teacher = teacher
    # def __repr__(self): # 必须有返回值,必须返回一个str类型
    #     return 'repr --> : %s,%s,%s,%s' % (self.name, self.price, self.period, self.teacher)

python = Course('python',1111,'12','Sheldon')
linux = Course('linux',2222,'12','Lins')
print('%r'%python)
print('%s'%python)
print(str(python))
print(repr(python))
#输出  str只能输出str方法,无法输出repr方法
<__main__.Course object at 0x00000000027E15C0>
str --> : python,1111,12,Sheldon
str --> : python,1111,12,Sheldon
<__main__.Course object at 0x00000000027E15C0>
View Code

__unicode__(self)   不常用,但是跟__str__ ,__repr__

定义对类的实例调用 unicode() 时的行为。 unicode() 和 str() 很像,只是它返回unicode字符串。注意,如果调用者试图调用 str() 而你的类只实现了 __unicode__() ,那么类将不能正常工作。所有你应该总是定义 __str__() .

class Course:
    def __init__(self,name,price,period,teacher):
        self.name = name
        self.price = price
        self.period = period
        self.teacher = teacher

    def __unicode__(self): # 必须有返回值,必须返回一个str类型
        return 'unicode --> : %s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher)

python = Course('python',1111,'12','Sheldon')
linux = Course('linux',2222,'12','Lins')
print('%r'%python)
print('%s'%python)
print(str(python))
print(repr(python))
#全部输出  unicode可以输出str,repr方法,但是是unicode字符串类型
<__main__.Course object at 0x00000000027C15C0>
<__main__.Course object at 0x00000000027C15C0>
<__main__.Course object at 0x00000000027C15C0>
<__main__.Course object at 0x00000000027C15C0>
View Code

容器背后的魔法

item系列方法

  • __getitem__(self,item)    表达方式 :obj.['xxx'] == >obj.xxx

定义对容器中某一项的使用self[key] 的方式进行读取操作时的行为。这也是可变和不可变容器类型都需要实现的一个方法。它应该在键的类型错误式产生 TypeError 异常,同时在没有与键值相匹配的内容时产生 KeyError 异常。

  • __setitem__(self,key,value)     表达方式:obj['xxx'] =yyy   ---> obj.xxx=yyy

定义对容器中某一项使用 self[key] 的方式进行赋值操作时的行为。它是可变容器类型必须实现的一个方法,同样应该在合适的时候产生 KeyError 和 TypeError 异常。  __iter__(self, key) 它应该返回当前容器的一个迭代器。迭代器以一连串内容的形式返回,最常见的是使用 iter() 函数调用,以及在类似 for x in container: 的循环中被调用。迭代器是他们自己的对象,需要定义 __iter__ 方法并在其中返回自己。

  • __delitem__(self,key)   del obj['xxx'] ===>  del obj.xxx

定义对容器中某一项使用 self[key] 的方式进行删除操作时的行为。 

class Course:
    def __init__(self,name,price,period,teacher):
        self.name = name
        self.price = price
        self.period = period
        self.teacher = teacher
    def __len__(self):
        return len(self.__dict__)
    def __getitem__(self, item):
        return self.__dict__[item]
    def __setitem__(self, key, value):
         self.__dict__[key] = value
    def __delitem__(self, key):
        self.__dict__.pop(key)
python = Course('python',1111,'12','Sheldon')
linux = Course('linux',2222,'12','Lins')
print(len(python))  # 输出 4
print(python['name'])  # 输出 python
print(python['price'])  # 输出 1111
python['name'] = 'python.2.0'  # 针对python.name 进行修改
print(python.name)  # python.2.0  发现已经被修改
del python['name'] # 执行删除python.name 操作
print(python.__dict__)  # {'price': 1111, 'period': '12', 'teacher': 'Sheldon'} 查看 python对象 发现 name被删除了
View Code

总结,有一些内置函数/模块要想正确的使用它们,那么必须按照它规定的语法来实现

__len__ (self)  很常用的方法  表现方式: object.__len__()

返回容器的长度,可变和不可变类型都需要实现。

class Ruler:
    def __init__(self,price,length,precision):
        self.price = price
        self.length = length
        self.precision = precision
    def __len__(self):
        return self.length
ruler = Ruler(3,20,0.1)
print(len(ruler))  #调用__len__方法后拿到长度  20
View Code

比较操作符系列  返回bool值

__cmp__(self,other)

__cmp__ 是所有比较魔法方法中最基础的一个,它实际上定义了所有比较操作符的行为(<,==,!=,等等),但是它可能不能按照你需要的方式工作(例如,判断一个实例和另一个实例是否相等采用一套标准,而与判断一个实例是否大于另一实例采用另一套)。 __cmp__ 应该在 self < other 时返回一个负整数,在 self == other 时返回False,在 self > other 时返回正整数。最好只定义你所需要的比较形式,而不是一次定义全部。 如果你需要实现所有的比较形式,而且它们的判断标准类似,那么 __cmp__ 是一个很好的方法,可以减少代码重复,让代码更简洁

  • __eq__(self,other) 定义等于操作符 == 的行为    

class Scientist:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        if self.name == other.name and self.age == other.name:
            return True
        return False
name1 = Scientist('Sheldon',29)
name2 = Scientist('Sheldon',29)

# print(name1 == name2)
# print(name1 is name2)
print(name1.__eq__(name2))   #这三种方法输出都False, name1 和name2 实例化后得到的内存地址不同,所以并不相同
View Code
  • __ne__(self,other) 定义不等于 != 行为

  • __lt__(self,other)  定义小于  <   行为

  • __gt__(self,other) 定义大于 >   行为

  • __le__(self,other) 定于小于等于 <= 行为

  • __ge__(self,other) 定于大于等于 >= 行为

 

 

 

 

 

 

 

 

 

 

 

 

...

posted @ 2018-11-28 00:02  FindSoul  阅读(274)  评论(0编辑  收藏  举报
var RENDERER = { POINT_INTERVAL : 5, FISH_COUNT : 3, MAX_INTERVAL_COUNT : 50, INIT_HEIGHT_RATE : 0.5, THRESHOLD : 50, init : function(){ this.setParameters(); this.reconstructMethods(); this.setup(); this.bindEvent(); this.render(); }, setParameters : function(){ this.$window = $(window); this.$container = $('#jsi-flying-fish-container'); this.$canvas = $('
'); this.context = this.$canvas.appendTo(this.$container).get(0).getContext('2d-disabled'); this.points = []; this.fishes = []; this.watchIds = []; }, createSurfacePoints : function(){ var count = Math.round(this.width / this.POINT_INTERVAL); this.pointInterval = this.width / (count - 1); this.points.push(new SURFACE_POINT(this, 0)); for(var i = 1; i < count; i++){ var point = new SURFACE_POINT(this, i * this.pointInterval), previous = this.points[i - 1]; point.setPreviousPoint(previous); previous.setNextPoint(point); this.points.push(point); } }, reconstructMethods : function(){ this.watchWindowSize = this.watchWindowSize.bind(this); this.jdugeToStopResize = this.jdugeToStopResize.bind(this); this.startEpicenter = this.startEpicenter.bind(this); this.moveEpicenter = this.moveEpicenter.bind(this); this.reverseVertical = this.reverseVertical.bind(this); this.render = this.render.bind(this); }, setup : function(){ this.points.length = 0; this.fishes.length = 0; this.watchIds.length = 0; this.intervalCount = this.MAX_INTERVAL_COUNT; this.width = this.$container.width(); this.height = this.$container.height(); this.fishCount = this.FISH_COUNT * this.width / 500 * this.height / 500; this.$canvas.attr({width : this.width, height : this.height}); this.reverse = false; this.fishes.push(new FISH(this)); this.createSurfacePoints(); }, watchWindowSize : function(){ this.clearTimer(); this.tmpWidth = this.$window.width(); this.tmpHeight = this.$window.height(); this.watchIds.push(setTimeout(this.jdugeToStopResize, this.WATCH_INTERVAL)); }, clearTimer : function(){ while(this.watchIds.length > 0){ clearTimeout(this.watchIds.pop()); } }, jdugeToStopResize : function(){ var width = this.$window.width(), height = this.$window.height(), stopped = (width == this.tmpWidth && height == this.tmpHeight); this.tmpWidth = width; this.tmpHeight = height; if(stopped){ this.setup(); } }, bindEvent : function(){ this.$window.on('resize', this.watchWindowSize); this.$container.on('mouseenter', this.startEpicenter); this.$container.on('mousemove', this.moveEpicenter); this.$container.on('click', this.reverseVertical); }, getAxis : function(event){ var offset = this.$container.offset(); return { x : event.clientX - offset.left + this.$window.scrollLeft(), y : event.clientY - offset.top + this.$window.scrollTop() }; }, startEpicenter : function(event){ this.axis = this.getAxis(event); }, moveEpicenter : function(event){ var axis = this.getAxis(event); if(!this.axis){ this.axis = axis; } this.generateEpicenter(axis.x, axis.y, axis.y - this.axis.y); this.axis = axis; }, generateEpicenter : function(x, y, velocity){ if(y < this.height / 2 - this.THRESHOLD || y > this.height / 2 + this.THRESHOLD){ return; } var index = Math.round(x / this.pointInterval); if(index < 0 || index >= this.points.length){ return; } this.points[index].interfere(y, velocity); }, reverseVertical : function(){ this.reverse = !this.reverse; for(var i = 0, count = this.fishes.length; i < count; i++){ this.fishes[i].reverseVertical(); } }, controlStatus : function(){ for(var i = 0, count = this.points.length; i < count; i++){ this.points[i].updateSelf(); } for(var i = 0, count = this.points.length; i < count; i++){ this.points[i].updateNeighbors(); } if(this.fishes.length < this.fishCount){ if(--this.intervalCount == 0){ this.intervalCount = this.MAX_INTERVAL_COUNT; this.fishes.push(new FISH(this)); } } }, render : function(){ requestAnimationFrame(this.render); this.controlStatus(); this.context.clearRect(0, 0, this.width, this.height); this.context.fillStyle = 'hsl(0, 0%, 95%)'; for(var i = 0, count = this.fishes.length; i < count; i++){ this.fishes[i].render(this.context); } this.context.save(); this.context.globalCompositeOperation = 'xor'; this.context.beginPath(); this.context.moveTo(0, this.reverse ? 0 : this.height); for(var i = 0, count = this.points.length; i < count; i++){ this.points[i].render(this.context); } this.context.lineTo(this.width, this.reverse ? 0 : this.height); this.context.closePath(); this.context.fill(); this.context.restore(); } }; var SURFACE_POINT = function(renderer, x){ this.renderer = renderer; this.x = x; this.init(); }; SURFACE_POINT.prototype = { SPRING_CONSTANT : 0.03, SPRING_FRICTION : 0.9, WAVE_SPREAD : 0.3, ACCELARATION_RATE : 0.01, init : function(){ this.initHeight = this.renderer.height * this.renderer.INIT_HEIGHT_RATE; this.height = this.initHeight; this.fy = 0; this.force = {previous : 0, next : 0}; }, setPreviousPoint : function(previous){ this.previous = previous; }, setNextPoint : function(next){ this.next = next; }, interfere : function(y, velocity){ this.fy = this.renderer.height * this.ACCELARATION_RATE * ((this.renderer.height - this.height - y) >= 0 ? -1 : 1) * Math.abs(velocity); }, updateSelf : function(){ this.fy += this.SPRING_CONSTANT * (this.initHeight - this.height); this.fy *= this.SPRING_FRICTION; this.height += this.fy; }, updateNeighbors : function(){ if(this.previous){ this.force.previous = this.WAVE_SPREAD * (this.height - this.previous.height); } if(this.next){ this.force.next = this.WAVE_SPREAD * (this.height - this.next.height); } }, render : function(context){ if(this.previous){ this.previous.height += this.force.previous; this.previous.fy += this.force.previous; } if(this.next){ this.next.height += this.force.next; this.next.fy += this.force.next; } context.lineTo(this.x, this.renderer.height - this.height); } }; var FISH = function(renderer){ this.renderer = renderer; this.init(); }; FISH.prototype = { GRAVITY : 0.4, init : function(){ this.direction = Math.random() < 0.5; this.x = this.direction ? (this.renderer.width + this.renderer.THRESHOLD) : -this.renderer.THRESHOLD; this.previousY = this.y; this.vx = this.getRandomValue(4, 10) * (this.direction ? -1 : 1); if(this.renderer.reverse){ this.y = this.getRandomValue(this.renderer.height * 1 / 10, this.renderer.height * 4 / 10); this.vy = this.getRandomValue(2, 5); this.ay = this.getRandomValue(0.05, 0.2); }else{ this.y = this.getRandomValue(this.renderer.height * 6 / 10, this.renderer.height * 9 / 10); this.vy = this.getRandomValue(-5, -2); this.ay = this.getRandomValue(-0.2, -0.05); } this.isOut = false; this.theta = 0; this.phi = 0; }, getRandomValue : function(min, max){ return min + (max - min) * Math.random(); }, reverseVertical : function(){ this.isOut = !this.isOut; this.ay *= -1; }, controlStatus : function(context){ this.previousY = this.y; this.x += this.vx; this.y += this.vy; this.vy += this.ay; if(this.renderer.reverse){ if(this.y > this.renderer.height * this.renderer.INIT_HEIGHT_RATE){ this.vy -= this.GRAVITY; this.isOut = true; }else{ if(this.isOut){ this.ay = this.getRandomValue(0.05, 0.2); } this.isOut = false; } }else{ if(this.y < this.renderer.height * this.renderer.INIT_HEIGHT_RATE){ this.vy += this.GRAVITY; this.isOut = true; }else{ if(this.isOut){ this.ay = this.getRandomValue(-0.2, -0.05); } this.isOut = false; } } if(!this.isOut){ this.theta += Math.PI / 20; this.theta %= Math.PI * 2; this.phi += Math.PI / 30; this.phi %= Math.PI * 2; } this.renderer.generateEpicenter(this.x + (this.direction ? -1 : 1) * this.renderer.THRESHOLD, this.y, this.y - this.previousY); if(this.vx > 0 && this.x > this.renderer.width + this.renderer.THRESHOLD || this.vx < 0 && this.x < -this.renderer.THRESHOLD){ this.init(); } }, render : function(context){ context.save(); context.translate(this.x, this.y); context.rotate(Math.PI + Math.atan2(this.vy, this.vx)); context.scale(1, this.direction ? 1 : -1); context.beginPath(); context.moveTo(-30, 0); context.bezierCurveTo(-20, 15, 15, 10, 40, 0); context.bezierCurveTo(15, -10, -20, -15, -30, 0); context.fill(); context.save(); context.translate(40, 0); context.scale(0.9 + 0.2 * Math.sin(this.theta), 1); context.beginPath(); context.moveTo(0, 0); context.quadraticCurveTo(5, 10, 20, 8); context.quadraticCurveTo(12, 5, 10, 0); context.quadraticCurveTo(12, -5, 20, -8); context.quadraticCurveTo(5, -10, 0, 0); context.fill(); context.restore(); context.save(); context.translate(-3, 0); context.rotate((Math.PI / 3 + Math.PI / 10 * Math.sin(this.phi)) * (this.renderer.reverse ? -1 : 1)); context.beginPath(); if(this.renderer.reverse){ context.moveTo(5, 0); context.bezierCurveTo(10, 10, 10, 30, 0, 40); context.bezierCurveTo(-12, 25, -8, 10, 0, 0); }else{ context.moveTo(-5, 0); context.bezierCurveTo(-10, -10, -10, -30, 0, -40); context.bezierCurveTo(12, -25, 8, -10, 0, 0); } context.closePath(); context.fill(); context.restore(); context.restore(); this.controlStatus(context); } }; $(function(){ RENDERER.init(); });