Process a list of instructions and output the max value reached Inputs looks like this 

b inc 5 if a &gt; 1
a inc 1 if b &lt; 5
c dec -10 if a &gt;= 1
c inc -20 if c == 10


I am concerned that I need to declare __max__ as global (but not __registers__). Any other recommendation on this Python script for a beginner ?

import sys
import re

steps = 0

__registers__ = []
__max__ = None

class Instruction:
    def __init__(self, string):
        # Group 1 is the register name,
        # Group 2 is inc or dec,
        # Group 3 is the amount to increase or decrease,
        # Group 4 is the full condition
        # Group 5 is the name of register against which the condition is tested,
        # Group 6 is the operand of the condition,
        # Group 7 is the numerical value of the second term of the condition
        regex = "(\w+)\s(inc|dec)\s(-*\d+)\sif\s((\w+)\s([^\w\s]+)\s(-*\d+))"
        regex_string = re.search(regex, string)
        if regex_string:
            self.name = regex_string.group(1)
            __registers__.append(Register(self.name, 0))
            self.oper = regex_string.group(2)
            self.amount = int(regex_string.group(3))
            self.condition = regex_string.group(4)
            self.tested_register = regex_string.group(5)
            self.test_operand = regex_string.group(6)
            self.test_value = int(regex_string.group(7))

    def process_instruction(self):
        # We do the test : 
        p =  str(find(self.tested_register).value)
        condition = self.condition.replace(self.tested_register, p)
        if eval(condition):
            # We apply the inc / dec amount : 
            reg = find(self.name)
            # print(reg.value)
            if self.oper == "inc":
                reg.value = reg.value + self.amount
            else:
                reg.value = reg.value - self.amount
            # print(reg.value)
            global __max__
            if __max__ is None or reg.value &gt; __max__:
                __max__ = reg.value

class Register:
    def __init__(self, name, value):
        self.name = name
        self.value = value

def find(register_name):
    for register in __registers__:
        if register.name == register_name:
            return register 

def get_max():
    max = None
    for regi in __registers__:
        if max is None or regi.value &gt; max:
            max = regi.value
    return max

def main(arguments):
    fileName = sys.argv[1]
    global instructions
    instructions = [Instruction(line.rstrip('\n')) for line in open(fileName)]
    # print(__registers__)
    # print(len(__registers__))
    global __max__
    for instru in instructions:
        instru.process_instruction()
    print(get_max())
    print(__max__)


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
As the comment threads make clear, the mystery about global goes away when you recognize the difference between accessing a variable from an outer scope (like your did with __registers___ and assigning to a variable whose name happens to also exist in an outer scope (what happened with __max__)

You can simplify a good bit of this by exploiting exactly this behavior.  If you store your registers in a module-level dictionary, you can access that dictionary in any part of the code without having to pass it around. Since you don't assign the dictionary -- you just access it -- you don't need to declare it global.  So in you case you could eliminate the find() function because you'd just grab a register value out of the dictionary.

 REGISTERS = {'a': 0, 'b': 1}

 def increment(reg, val):
     REGISTERS[reg] += val


would be an example.  In this case we can be a bit lazy and use a dictionary comprehension -- a shorthand way to fill out a dictionary with keys from 'a' to 'z' and values of all zeros:

import string  # the string module has a builtin for the ascii alphabet
REGISTERS = {char: 0 for char in string.ascii_lowercase}


So you don't need a register class -- you just manipulate the values in the dictionary for each register.

To do the instruction parsing, you can simplify things a good bit by eliminating the regex and simply using Python's builtin string split() function, which will take a string like  'b inc 5 if a > 1' and turn it into ['b', 'inc', '5', 'if', 'a', '>', '1'] without any extra work (this would not be appropriate if any of your directives had spaces in them -- but they don't seem to in this example).  That gives you 7 tokens -- your comment here was very useful -- 3 describing the tests you want to apply and three describing the operation to perform in the test passes (#3, the if, is basically ignorable).

With everything already parsed out, you really don't need to use classes.  The Instruction class does only two things: it applies the test in the last three tokens, and if that test is true it uses the instructions in the first three tokens to change the register.  Python has a handy built-in way to do what you're trying to do -- capturing common operations like addition or comparison.  The operator module has a bunch of functions which correspond to the basic operations. For example 'inc' corresponds to operator.iadd which is basically a += b expressed as a function.  '>' becomes operator.gt, a function that returns true if the first of its arguments is greater than the second.   

That would get rid of much of the logic in your Instruction class.  Another module level 'global' dictionary is an easy way to map the strings to the operator,  simplifying both the process of parsing -- no conditional checks, just dictionary lookups -- and of running the tests.  So, first a dictionary to do the mapping:

# match operator functions to string identifiers
OPERANDS = {
    'inc': operator.iadd,
    'dec': operator.isub,
    '&gt;': operator.gt,
    '&gt;=': operator.ge,
    '&lt;': operator.lt,
    '&lt;=': operator.le,
    '==': operator.eq,
    '!=': operator.ne
}


and with that in place the functions to use these operators are very simple. If you want to apply some operation to a register, you get the value from the REGISTERS dictionary, the operator from the OPERANDS dictionary, then call the operator with your value:

def apply_value(register, opstring, valstring):
    operator = OPERANDS[opstring]
    value = float(valstring)
    orig = REGISTERS[register]
    REGISTERS[register] = operator(orig, value)


doing the test ('is this larger than 5' or whatever) is equally simple:

def condition(register, teststring, testval):
    check = OPERANDS[teststring]
    value = float(testval)
    existing = REGISTERS[register]
    return check(existing, value)


So as you parse a line of instructions, you just run condition function on the last three tokens ("a > 5") and if it's true, run the apply_value function on the first three:

    with open(filename, 'rt') as fileread:
        for directive in fileread:
            tokens = directive.split()  # [3] is always 'if', so ignored
            if condition(tokens[4], tokens[5], tokens[6]):
                apply_value(tokens[0], tokens[1], tokens[2])


If you run that on all your directives you'll see the register values going up and down.  Python also has an easy built-in way to find the maximum value in a series -- so to get the largest register value it's just 

    max_value = max(REGISTERS.values())


with no need for you to track the max value manually.

Putting it all together it might look like this:

import sys
import operator
import string

# match operator functions to string identifiers
OPERANDS = {
    'inc': operator.iadd,
    'dec': operator.isub,
    '&gt;': operator.gt,
    '&gt;=': operator.ge,
    '&lt;': operator.lt,
    '&lt;=': operator.le,
    '==': operator.eq,
    '!=': operator.ne
}

# REGISTERS is a dictionary with names as keys, initialized to 0's
REGISTERS = {char: 0 for char in string.ascii_lowercase}


def apply_value(register, opstring, valstring):
    operator = OPERANDS[opstring]
    value = float(valstring)
    orig = REGISTERS[register]
    REGISTERS[register] = operator(orig, value)


def check_condition(register, teststring, testval):
    check = OPERANDS[teststring]
    value = float(testval)
    existing = REGISTERS[register]
    return check(existing, value)

if __name__ == '__main__':
    filename = sys.argv[-1]
    with open(filename, 'rt') as fileread:
        for directive in fileread:
            tokens = directive.split()  # [3] is always 'if', so ignored
            if check_condition(tokens[4], tokens[5], tokens[6]):
                apply_value(tokens[0], tokens[1], tokens[2])


    max_value = max(REGISTERS.values())
    for name, value in REGISTERS.items():
        if value == max_value:
            print ("highest register:", name, value)


As with many problems in Python, the rich offerings in the standard library often let you get away with just simple functions instead of lots of custom classes.