python光学仿真中面向对象的光学元件类是如何实现的?很多新手对此不是很清楚。为了帮助大家解决这个问题,下面小编就为大家详细讲解一下。有这种需求的人可以学习,希望你能有所收获。
00-1010平面镜是一个非常简单的模型,因为我们只需要考虑一个平面。然而,其他光学元件可能会变得有些复杂:我们必须考虑光在入射表面和出射表面上的行为。
这当然是无稽之谈,我们有一个初步的解决方案:将光学元件分为正面和背面。如果光需要在光学元件中被多次反射,那么光学元件可以被分割成需要多次反射的多个面,这在没有大脑的情况下是完美的。
这说明我们熟悉程序员的思维,我们眼中的世界不再是你看到的就是你得到的世界,而是我们看到的是抽象部分的表现。但是不要慌,程序员和正常人可能没有太大的区别,因为我们不仅可以拆解这个世界,还可以将拆解后的零件重构回这个世界。
试着把问题变得更复杂。光学系统中有很多光学元件,光会多次通过每个光学元件,每次入射点和出射点都会有一定的偏差。光学元件可能吸收光能,从而产生热量。而且每次入射点和出射点不同时,加热位置也会不一样。因为热会导致光学元件变形,所以光和光学元件的效果下次也会改变。
也就是说,对于每个光学元件,不仅有固定的正面和背面,而且还有不断变化的参数,如入射点、出射点、发热和变形。这样一个实际问题促使我们构造一个更接近现实的数据类型。换句话说,我们想要创建一个可以封装各种变量和函数的对象。当我们输入一个参数时,对象的状态也会改变。
这叫做面向对象。
classOpti():
def__init__(self,edge1,edge2):
self.edge1=edge1
Self.edge2=edge2在上面的例子中,我们定义了一个光学元件类,它有两个表面,可以是平面的,也可以是曲面的。就这样,我们成立了一个班级。其中__init__是初始化方法,self代表我们创建的类。一般来说,如果一个类中的一个方法没有被修改,那么self必须作为第一个参数。
Self.edge1表示此Opti类中有一个名为edge1的成员。当这个类被初始化时,我们可以给它赋值。
有些元件可能只有一个表面,如全反射镜;有些可能有多个表面,如偏振立方体。而且,我们在做实验的时候,还需要比较不同的光学元件,才能得到最好的实验结果。那么,如果我们想改变已经建成的光学元件,我们应该怎么做呢?
其实很简单,只需添加一个方法,这样就可以插入或删除一个新的曲面。
#文件Opti.py
classOpti():
def__init__(self,edges=[[(0,-1),(0,1)],[(0,1),(0,-1),(1/2,0)]):
self.edges=[{'index':i,' dots':edges[i]}
foriirange(len(edges))]
#edge的格式是(dot1,dot2,).
定义边缘(自身、边缘、反照率=0):
self.edges.append(
{“index”: len(self . edges)、“dots”: edge })
#可接受的数量和点集。
定义边缘(自身,边缘):
(=NationalBureauofStandards)国家标准局
p; try:
if isinstance(edge,list): #如果edge的类型是list
for edg in self.edges:
if edg['dots']==edge:
edge = edg['index']
del self.edges[edge]
except:
print("no this edge")
在上面的代码中,可以看到初始化函数被预设了一些值,这点与普通函数并无二致。我们可以看到,默认插入的两个曲面分别是平面[(0,-1),(0,1)]
和弧面[(0,1),(0,-1),(1/2,0)]
,可见默认生成一个平凸镜。
成员变量self.edges
即光学表面的列表,每个光学表面有两个参数,分别是索引index
和点集dots
。由此前的光学抽象可知,当点对中有两个点的时候,代表平面;有三个点的时候,代表弧面。
方法insertEdge
为插入一个光学表面,其中,编号为这个光学表面在self.edges
中的索引号;delEdge
顾名思义为删除某个光学表面。如果传入的edge
为一个列表,则说明传入的是一个参数确定的曲面,此时通过遍历self.edges
找到这个表面,并得到其索引。
如果传入的参数为一个单值,那么说明传入的是索引号,所以直接删除即可。
在这个方法中,使用了一种新的代码块try:...except...
,这是一种异常机制,即尝试运行try:
块中的代码,如果运行失败,则执行except
。如果我们没能执行成功delEdge
,则说明我们输入的表面并不在这个光学元件中,所以输出"no this edge"
。
这好像是第一次看到print
这个命令呢,一般来说这应该是最先接触到的函数,毕竟对于大多数程序员来说,敲下的第一行代码就是
print("hello world") print('hello world')
同时,我们除了数值类型之外,又认识了另一种数据类型,即字符。在python中,可以通过双引号或者单引号来表示单个字符或者字符串。即上述的hello world代码中,两行均正确,而且没什么区别。
现在,我们已经写了一个类,于是可以创建一个对象,在命令行中输入:
>>> from Opti import Opti >>> Opti.__name__ #这是什么鬼 'Opti' >>> x = Opti() #创建对象,由于未输入参数,故皆为默认值 >>> x.edges #现实类成员 [{'index': 0, 'dots': [(0, -1), (0, 1)]}, {'index': 1, 'dots': [(0, 1), (0, -1), (0.5, 0)]}] >>> x.delEdge(1) #调用类方法 >>> x.edges #果然少了一个边 [{'index': 0, 'dots': [(0, -1), (0, 1)]}] >>> x.delEdge(1) #删除不存在的边是不可能的 no this edge >>>
首先,from Opti import Opti
的这两个Opti并不相同,前者代表包`Opti.py',后者代表Opti.py中的类'Opti',import之后便可以调用了。
然后出现了一个比较吊诡的事情,我们在类中并没有定义__name__
,然而调用之后却有值产生。
请勿惊慌,其实是老熟人了。可以将__name__
理解为python内部的内置属性,当我们直接执行某一.py文件时,这个__name__
的值为__main__
,否则的话就是类的名字。所以,到这个时候,我们似乎应该能明白入口函数的真正意义了吧。
继续向下,几乎所有的事情就都不出所料了。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/37087.html