31 oct. 2022

[Dynamo =+ Python] Paramètre sortant (out Parameters) en Python

 


Python Halloween Parameter by #craiyon



Cet article traite de la mise en œuvre et utilisation des paramètres sortant "out Parameters" avec Python.

if this article is not in your language, use the Google Translate widget  (bottom of page for Mobile version ) 


Le paramètre out en C# est utilisé pour passer des arguments aux méthodes par référence. Il est généralement utilisé lorsqu'une méthode renvoie plusieurs valeurs.

En Python, ce concept n'existe pas, une fonction peut renvoyer directement plusieurs valeurs via un tuple.
Cependant, dans certains cas, il peut être intéressant de retrouver un usage similaire.

  • Usage similaire avec une fonction Python 

Prenons pour exemple une fonction qui teste si deux points sont proches, comme nous passons cette fonction dans une instruction conditionnelle (if...), la fonction doit obligatoirement retourne un booléen (True/False) 

ce qui donne le code suivant


Maintenant, en plus de la valeur booléenne, nous souhaitons récupérer la distance 👀 🤔

    • solution 1 : retourner un tuple 
ici, on retourne un booléen et la distance associée (du coup, on ne peut pas passer directement l'appel de la fonction dans le bloc "if")

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

def is_nearset(pta, ptb):
    distance = pta.DistanceTo(ptb)
    return distance < 0.5, distance

scatter_points = IN[0]
pt_test = IN[1]
out = []

for p in scatter_points:
    test, value = is_nearset(pt_test, p)
    if test:
        out.append([p, value])

OUT = out

    • solution 2 : utiliser une variable globale

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

def is_nearset(pta, ptb):
    global distance
    distance = pta.DistanceTo(ptb)
    return distance < 0.5

scatter_points = IN[0]
pt_test = IN[1]
distance = 0
out = []

for p in scatter_points:
    if is_nearset(pt_test, p):
        out.append([p, distance])

OUT = out

    • solution 3 : passer un argument, une référence ou un attribut d'une classe

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
from collections import namedtuple

def is_nearset(pta, ptb, outPara):
    distance = pta.DistanceTo(ptb)
    outPara.Value = distance
    return distance < 0.5

scatter_points = IN[0]
pt_test = IN[1]
out = []

for p in scatter_points:
    wrapDistance = namedtuple('Distance', ['Value'])
    if is_nearset(pt_test, p, wrapDistance):
        out.append([p, wrapDistance.Value])

OUT = out

    • solution 4 : utiliser un attribut de fonction
 ma solution préférée 😎

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

def is_nearset(pta, ptb):
    is_nearset.distance = pta.DistanceTo(ptb)
    return is_nearset.distance < 0.5

scatter_points = IN[0]
pt_test = IN[1]
out = []

for p in scatter_points:
    if is_nearset(pt_test, p):
        out.append([p, is_nearset.distance])

OUT = out


Résultats 


  • Exemple d'utilisation avec une méthode .Net (API) et IronPython 
Dans cet exemple, nous cherchons le point d'intersection entre 2 canalisations avec la méthode Intesect
Pour ce faire, un type de référence ('outRef_InterR') est passé en argument où IronPython stockera la valeur du paramètre mis à jour.
Le type de Référence doit être le même que le "out Parameter"



import clr
import sys
import System

clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

pipeA = UnwrapElement(IN[0])
pipeB = UnwrapElement(IN[1])

curveA = pipeA.Location.Curve
curveB = pipeB.Location.Curve

outRef_InterR = clr.Reference[IntersectionResultArray]()
if curveA.Intersect(curveB, outRef_InterR) == SetComparisonResult.Overlap:
	OUT = outRef_InterR.Value[0].XYZPoint
https://ironpython.net/documentation/dotnet/dotnet.html#ref-and-out-parameters

  • Exemple  d'utilisation avec une méthode .Net (API) et PythonNet
Le même exemple avec CPython3/PythonNet, ici la syntaxe est différente, il faut passer une variable factice ('dummy_InterR') en argument.
Le résultat est retourné sous forme de tuple (retour de la méthode + valeur du paramètre) 
Le type de la variable factice doit être le même que le "out Parameter"
 

import clr
import sys
import System

clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

pipeA = UnwrapElement(IN[0])
pipeB = UnwrapElement(IN[1])

curveA = pipeA.Location.Curve
curveB = pipeB.Location.Curve
#
# create a dummy variable
dummy_InterR = IntersectionResultArray()
setInterResult, resultArray = curveA.Intersect(curveB, dummy_InterR)
if setInterResult == SetComparisonResult.Overlap:
    OUT = resultArray[0].XYZPoint
https://pythonnet.github.io/pythonnet/python.html#out-and-ref-parameters

 

Python Halloween by #craiyon





0 commentaires:

Enregistrer un commentaire