Home > database >  How to iterate through the same line of python code but with different variables and attributes
How to iterate through the same line of python code but with different variables and attributes

Time:10-19

as you can see i am writing the same code over and over again, how can i make an algorithm so to say, to iterate just a list of the parameters through the same line of code. Is that possible in this scenario or not. What i am doing is i am programming some values into a device through a serial connection. I want to automate it so yeah. This code works perfectly fine but i want to know how to write an algorithm to iterate through only the parameters. as yo can see only the .encode() value and the ft value is different in every line An example would be very helpful.

def write_par(self):    
        try:
            reset_input = self.ser.reset_input_buffer()
            reset_input
    
            self.ser.write('\r\nft_seton ordoxo '.encode()   self.artikel_va.encode()   '\r\n'.encode())
            reset_input
            time.sleep(1.0)
                        
            self.ser.write('ft_seton hrdver '.encode()   self.HVVV.encode()   '\r\n'.encode())
            reset_input
            time.sleep(1.0)
            
            self.ser.write('ft_seton hrdbrd '.encode()   self.HWB.encode()   '\r\n'.encode())
            reset_input
            time.sleep(1.0)
        
            self.ser.write('ft_seton srll '.encode()   self.serien_nummer.encode()   '\r\n'.encode())
            reset_input
            time.sleep(1.0)
        
            self.ser.write('ft_seton addr '.encode()   self.mac.encode()   '\r\n'.encode())
            reset_input
            time.sleep(1.0)
        

    
        except Exception:
            print('Device parameters were not written')
            pass

CodePudding user response:

Just use the Python for functionality - it will always work as a "for each" and give you each element in a series.

You can either organize the names and attributes as tuples, or use the zip call:

def write_par(self):    
        try:
            reset_input = self.ser.reset_input_buffer  # <- NB. no () in this line, otherwise it is called a single time
            self.ser.write("\r\n")
    
            for name, value in [
                ("ortodoxo", self.artikel_va),
                ("hrdver", self.HVVV),
                ("hrdbrd", self.HWB),
                ("srll", self.serien_nummer),
                ("addr", self.mac),
            ]:
    
                self.ser.write(f'nft_seton {name} {value)\r\n'.encode()
                reset_input()
                time.sleep(1.0)
                       
    
        except Exception as error:
            print(f'Device parameters were not written: at {name} we got {error}')
            pass

As you can see, also: Python is not Basic, and there is no need to concatenate strings by opening and closing quotations and using the operator. The "f-string" syntax will serve you well.

Another good practice is to print out what went wrong: you have that information while the program is running, and it is basically free to print it. If you print just "could not do it", that just means headaches that could have been avoided downstream.

Also, the first string to be printed out is different in your code: "nft_seto" vs "nt_seton" in your code. I assumed that was a typo. Otherwise, if you really need then to be different, just include this first string in the tuples, in the for loop and add another variable to carry it.

CodePudding user response:

As others commented, put the statements to be executed repeatedly into a separate function. Something like this:

def write_something(self, name, value):
    self.ser.write(name.encode()   value.encode()   '\r\n'.encode())
    self.ser.reset_input_buffer()
    time.sleep(1.0)

def write_par(self):    
    try:
        write_something('\r\nft_seton ordoxo ', self.artikel_va)
        write_something('ft_seton hrdver ', self.HVVV)
        ...
    except Exception:
        print('Device parameters were not written')
        pass

CodePudding user response:

Ignoring the sleep() calls (not sure why they're there) and also the NOOPs.

Build a control structure and iterate over it like this:

def write_par(self):
    CONTROL = {
        '\r\nft_seton ordoxo': 'artikel_va',
        'ft_seton hrdver': 'HVVV',
        'ft_seton hrdbrd': 'HWB',
        'ft_seton srll': 'serien_nummer',
        'ft_seton addr': 'mac'
    }

    try:
        self.ser.reset_input_buffer()

        for k, v in CONTROL.items():
            self.ser.write(f'{k} {getattr(self, v)}\r\n'.encode())

    except Exception:
        print('Device parameters were not written')

CodePudding user response:

When you are trying to remove repetition from code there are two general approaches:

  1. Create a helper function
    In this method we create a function which we call multiple times
    This makes our code cleaner and easier to understand
    If we wanted to apply this to your code

    def write_par(self):    
         try:
             reset_input = self.ser.reset_input_buffer()
             reset_input
    
             self.write_ser('\r\nft_seton ordoxo ', self.artikel_va.encode())
             self.write_ser('ft_seton hrdver ', self.HVVV.encode())
             self.write_ser('ft_seton hrdbrd ', self.HWB.encode())
             self.write_ser('ft_seton addr ', self.mac.encode())
    
         except Exception:
             print('Device parameters were not written')
             pass
    ### Helper Methods ###
    def write_ser(self, text, frmt):
        """ 
        Writes a piece of text in encoded format 
    
        Inputs
            :text: <str> to be written, i.e '\r\nft_seton ordoxo '
            :frmt: <obj> to use for encoding, i.e self.artikel_va.encode()
        """
        # TODO: think about how you would implement this 
        # (hint: you already have)
        pass
    
  2. Use a loop
    With a loop we are able to reduce the number of times we repeat a piece of code
    This is done by storing the different parts in each line inside some variable, usually a list, and iterating through it.
    At every iteration you will perform what is shared by each of the lines.
    If we wanted to apply this to your code

    def write_par(self):    
         try:
             reset_input = self.ser.reset_input_buffer()
             reset_input
    
             inputs = [
               ('\r\nft_seton ordoxo ', self.artikel_va.encode()),
               ('ft_seton hrdver ', self.HVVV.encode()),
               ('ft_seton hrdbrd ', self.HWB.encode()),
               ('ft_seton hrdbrd ', self.HWB.encode()),
               ('ft_seton addr ', self.mac.encode())
             ]
    
             for text, frmt in inputs:
                # TODO: Again you think about how you would implement this 
    
         except Exception:
             print('Device parameters were not written')
             pass
    

Which approach you should take will depend on what your code does, in your case either option would work, even a mix of both approaches would work!

CodePudding user response:

Define a function to handle this like so

def write_encoded_values(str_a, str_b):
    self.ser.write(f'{str_a}{str_b}\r\n'.encode())

then you can call it like this for example

self.write_encoded_values('\r\nft_seton ordoxo ', self.artikel_va)
  • Related